当前位置: 首页 > 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));}    
}

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

 

 

http://www.xdnf.cn/news/368623.html

相关文章:

  • 机舱巡飞平台技术要点突破点详解!
  • 流式渲染 Streaming SSR
  • deep seek简介和解析
  • BERT模型讲解
  • 【C语言指针超详解(三)】--数组名的理解,一维数组传参的本质,冒泡排序,二级指针,指针数组
  • 开平机:技术深水区与产业变革的融合突破
  • spring ai alibaba ChatClient 获取大模型返回内容的方式 以及使用场景
  • 什么是 HEIC 格式?如何在电脑上查看HEIC格式的图像?
  • 软件开发的图表类型
  • RAG优化知识库检索(1):基础概念与架构
  • 结构性变革与新兴机遇
  • 如何评估SAP升级实施商的专业能力?
  • JWT原理及工作流程详解
  • 高频算法面试题总结
  • 系统的从零开始学习电子的相关知识,该如何规划?
  • 高效处理CR
  • 耀圣-气动带刮刀硬密封法兰球阀:攻克颗粒高粘度介质的自清洁 “利器”
  • (八)Java面向对象编程三大特性:封装、继承与多态性详解
  • Linux 系统安装Minio详细教程
  • 音视频同步知识
  • 今日行情明日机会——20250509
  • Codeforces Round 1023 (Div. 2)
  • 反向沙箱介绍
  • 麒麟系统使用-个性化设置
  • 库室指静脉人脸门禁机 LK-BM-S10C/JR
  • CDGP|数据治理怎么带动企业高速发展?
  • 革新锅炉厂智能控制——Ethernet IP转CANopen协议网关的工业互联新方案
  • 【UltralyticsYolo11图像分类完整项目-04】代码重构
  • 出现在‘{‘的段错误
  • 【RAG官方大神笔记】检索增强生成 (RAG):Python AI 教程的详细介绍