当前位置: 首页 > news >正文

java-多态

一、多态的来历


我们先来了解一个业务场景:请设计一个系统,描述主人喂养宠物的场景,首先在这个场景当中应该有”宠物对象“,“宠物对象”应该有一个吃的行为,另外还需要一个“主人对象”,主人应该有一个喂的行为,请看代码:

//小猫

public class Cat{String name;public Cat(String name) {this.name=name;}public  void eat() {System.out.println(this.name+"正在吃鱼");}}

//主人

public class Person {String name;public Person(String name) {this.name=name;}public void feed(Cat cat) {System.out.println(this.name+"拿出来了好多小鱼");cat.eat();System.out.println(cat.name+"十秒钟吃了10条小鱼");}
}

//测试类

public class Test1 {public static void main(String[] args) {Cat cat = new Cat("小花");Person person1= new Person("小明");person1.feed(cat);}}

测试结果:

现在我们已经创建了一个喂养宠物的场景,但是我们想一想,假如家里又来了几只宠物你会怎么办

与小猫类的代码一样,我们可以创建小狗类,小猪类,小牛类........


public class Pig {String name;...}//吃的行为public void eat(){...}
}

public class Dog {String name;...}//吃的行为public void eat(){...}
}

public class Cow {String name;...}//吃的行为public void eat(){...}
}

 如果主人想要喂养它们,我们还需要主人的源代码,这是让程序员无法容忍的,如果这个人养了上千种动物,就意味着你需要增改上千次

//主人

 

public class Person {String name;public Person(String name) {this.name=name;}public void feed(Cat cat) {System.out.println(this.name+"拿出来了好多小鱼");cat.eat();System.out.println(cat.name+"十秒钟吃了10条小鱼");}public void feed(Dog dog) {System.out.println(this.name+"拿出来了好多骨头");dog.eat();System.out.println(dog.name+"十秒钟吃了10根骨头");}//feed pig.....//feed cow..........这个博主有点小懒
}

 //测试类

public class Test1 {public static void main(String[] args) {Cat cat = new Cat("小花");Dog dog = new Dog("旺财"); Person person1= new Person("小明");person1.feed(cat);person1.feed(dog);//person1.feed(pig)   person1.feed(Cow);System.out.println("   ");System.out.print("博主省略了猪和牛,就知道多繁琐了");}}

测试结果:
 

  那么如何解决这个问题呢????????你猜对了-------就是多态!

我们都知道小猫小狗...都属于宠物,也就是说宠物类是单个宠物的父类

请看代码:
 

public class Pet {String name;//吃的行为public void eat(){}
}

//小猫

public class Cat extends Pet{public Cat(String name) {this.name=name;}public  void eat() {System.out.println(this.name+"正在吃鱼");}}

//小狗

public class Dog  extends Pet{public Dog(String name) {this.name=name;}public void eat() {System.out.println(this.name+"正在啃骨头");}
}


//主人

public class Person {String name;public Person(String name) {this.name=name;}public void feed(Pet pet) {System.out.println("主人正在喂食");pet.eat();System.out.println("主人喂食完毕");}}

//测试类
 

public class Person {String name;public Person(String name) {this.name=name;}public void feed(Pet pet) {System.out.println("主人正在喂食");pet.eat();System.out.println("主人喂食完毕");}}

测试结果 


 

与上面的结果是等价的,在主人类中我们节省了很多力气

 

总结,上面的程序代码中,主人(Person类)中的feed(Pet pet)的参数类型定义为更加抽象的Pet类型,而不是具体的Cat宠物,或者Dog宠物。那假如说主人又养了一个小牛,我们要增加一个”小牛类“,然后Pig 继承宠物类Pet,并重写eat()方法,然后修改一下测试类就行了,整个过程我们不需要修改Person类,只是额外增加了一个新的类

public class Pig extends Pet{public Pig(String name) {this.name=name;}public void eat() {System.out.println(this.name+"小猪正在进食");}
}

//测试类

public class Test1 {public static void main(String[] args) {Cat cat = new Cat("小花");Dog dog = new Dog("旺财"); Pig pig = new Pig("猪哼哼");Person person1= new Person("小明");person1.feed(cat);person1.feed(dog);person1.feed(pig);}}

 测试结果:

从上面例子表可以感受到多态的使用大大节省了内存与算力!

二、那究竟什么是多态?

多态是同一个行为具有多个不同表现形式和形态的能力
 

三、多态实现的必要条件

1.子类必须继承父类

2.必须有重写

3.父类引用指向子类对象------>向上转型

我在下面将采用内存图的形式向你展示,多态的过程,方便你理解

我们首先要知道,多态语句的构成

Pet cat=new Cat();

//Pet:类名

//cat:变量

//new:关键字

//Cat():构造器

Pet cat=new Cat();

会在堆区生成一个Pet对象 cat存储Pet对象的地址,而不是存储Cat对象的地址

重点:父类方法被重写之后,会生成一个指针指向子类重写的方法

//小猫类

public class Cat extends Pet{public Cat(String name) {this.name=name;}public  void eat() {System.out.println(this.name+"正在吃鱼");}public void jump() {System.out.println("小猫跳的很高");}}

//父类

public class Pet {String name;//吃的行为public void eat() {}
}

//主人

public class Person {String name;public Person(String name) {this.name=name;}public void feed(Pet pet) {System.out.println("主人正在喂食");pet.eat();System.out.println("主人喂食完毕");}}

//测试类

public class Test1 {public static void main(String[] args) {Pet cat = new Cat("小花");cat.eat();	}}

结果:

 

接下来我们来画一下内存图

看到 cat变量指向的是Pet类,Cat对eat()方法进行了重写,指针指向,所以才能调取到Cat类中的eat()方法

那就有人会问了 能不能调用jump()方法呢

试一试!
 

答案是不行,因为我们观察内存图,jump()方法并未被调取,除非jump()方法是对父类方法的重写! 

四、测试练习!

//父类

public class A {public String show(D obj) {return "A and D";}public String show(A obj) {return "A and A";}
}

//各子类

public class B extends A{public String show(Object obj) {return "B and B";}public String show(A obj) {return "B and A";}}
public class D extends B{}

public class C extends B{}

//测试类

public class Test {public static void main(String[] args) {A a1=new A();A a2 = new B();B b = new B();C c= new C();D d= new D();System.out.println(a1.show(b));System.out.println(a1.show(c));System.out.println(a1.show(d));System.out.println(a2.show(b));System.out.println(a2.show(c));System.out.println(a2.show(d));System.out.println(b.show(b));System.out.println(b.show(c));System.out.println(b.show(d));}    
}

 请你说出测试结果!!!!!最好用画内存的方法,去解决问题,更加清晰!!!
测试结果:

 

 

相关文章:

  • 线程中常用的方法
  • Java反射 八股版
  • Vue3 官方宣布淘汰 Axios,拥抱Alova.js
  • 44.辐射发射整改简易摸底测试方法
  • [250509] x-cmd 发布 v0.5.11 beta:x ping 优化、AI 模型新增支持和语言变量调整
  • Linux C语言线程编程入门笔记
  • 考研英一学习笔记 2018年
  • 股票行情实时数据:港股、美股、沪深A股行情数据的具体细分内容介绍在哪里可以获取到便宜的股票实时行情?
  • 【Linux】深入拆解Ext文件系统:从磁盘物理结构到Linux文件管理
  • 传统销售VS智能销售:AI如何重构商业变现逻辑
  • 第J7周:ResNeXt解析
  • 【“星睿O6”AI PC开发套件评测】+ MTCNN 开源模型部署和测试对比
  • 重构 cluster-db 选择器,新增限制字段 showDb 不影响原功能前提实现查询功能增量拓展
  • CSS display: none
  • linux0.11内核源码修仙传第十六章——获取硬盘信息
  • 5G让媒体传播更快更智能——技术赋能内容新时代
  • PostgreSQL可见性映射VM
  • 高性能编程相关
  • PHP会话技术
  • 运用fmpeg写一个背英文单词的demo带翻译
  • 要更加冷静地看待“东升西降”的判断
  • 中俄就应对美加征所谓“对等关税”等问题进行深入交流
  • 读图|展现城市品格,上海城市影像走进南美
  • 警惕“全网最低价”等宣传,市监总局和中消协发布直播消费提示
  • 泽连斯基称与特朗普通话讨论停火事宜
  • 陕南多地供水形势严峻:有的已呼吁启用自备水井