0224多态

news/2024/3/29 4:27:48/文章来源:https://blog.csdn.net/wjkqq0921/article/details/129193983

目录

一、多态的引入

二、方法的多态

一、重载

二、重写

 三、对象的多态(核心)

四、应用实例

 五、向上转型

六、向下转型

七、属性没有重写

八、练习题

第一题

 第二题


一、多态的引入

通过主人给宠物喂食这个例子,说明多态的必要性:可以提高代码的复用性

二、方法的多态

一、重载

package com.hspedu.poly_;public class PolyMethod {public static void main(String[] args) {A a = new A();System.out.println(a.sum(10,20));System.out.println(a.sum(10,20,30));}
}
class B { //父类public void say() {System.out.println("B say() 方法被调用...");}
}
class A extends B {//子类public int sum(int n1, int n2){//和下面 sum 构成重载return n1 + n2;}public int sum(int n1, int n2, int n3){return n1 + n2 + n3;}public void say() {System.out.println("A say() 方法被调用...");}
}

二、重写

子类-B类重写了父类-A类的say()方法

package com.hspedu.poly_;public class PolyMethod {public static void main(String[] args) {A a = new A();System.out.println(a.sum(10,20));System.out.println(a.sum(10,20,30));System.out.println("==============");B b = new B();b.say();//调用父类的say()方法a.say();//调用子类的say()方法}
}
class B { //父类public void say() {System.out.println("B say() 方法被调用...");}
}
class A extends B {//子类public int sum(int n1, int n2){//和下面 sum 构成重载return n1 + n2;}public int sum(int n1, int n2, int n3){return n1 + n2 + n3;}public void say() {System.out.println("A say() 方法被调用...");}
}

 三、对象的多态(核心)

四条必背知识点:

1)编译类型看对象的左边,运行类型看对象的右边

2)编译类型和运行类型可以不一致(当然也可以一致)

3)编译类型在定义对象时就已经确定了,不能改变

4)运行类型可以改变

eg:

Animal  animal  =  new Dog();//

父类的对象引用指向子类的对象本身

animal 编译类型就是 Animal , 运行类型 Dog

animal  =  new Cat();

编译类型还是Anmal,运行类型从Dog变成了Cat

package com.hspedu.poly_.objectpoly_;public class Animal {public void cry(){System.out.println("Animal cry() 动物在叫....");}
}
package com.hspedu.poly_.objectpoly_;public class Dog extends Animal{@Overridepublic void cry() {System.out.println("Dog cry() 小狗汪汪叫...");}
}
package com.hspedu.poly_.objectpoly_;public class Cat extends Animal{@Overridepublic void cry() {System.out.println("Cat cry() 小猫喵喵叫...");}
}
package com.hspedu.poly_.objectpoly_;public class PolyObject {public static void main(String[] args) {//体验对象多态特点//animal 编译类型就是 Animal , 运行类型 DogAnimal animal = new Dog();//因为运行时,执行到该行时,animal 运行类型是 Dog,所以 cry 就是 Dog 的 cryanimal.cry();//调用Dog的cry()方法//运行类型发生了改变//animal 编译类型 Animal,运行类型就是 Catanimal = new Cat();animal.cry();//调用Cat的cry()方法}
}

披着羊皮的狼:外形是羊(编译类型),内在是狼(运行类型)

四、应用实例

宠物喂食的例子

Animal类和它的子类

package com.hspedu.poly_;public class Animal {private String name;public Animal(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
package com.hspedu.poly_;public class Cat extends Animal{public Cat(String name) {super(name);}}
package com.hspedu.poly_;public class Dog extends Animal{public Dog(String name) {super(name);}
}

Food和它的子类 

package com.hspedu.poly_;public class Food {private String name;public Food(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
package com.hspedu.poly_;public class Fish extends Food{public Fish(String name) {super(name);}
}
package com.hspedu.poly_;public class Bone extends Food{public Bone(String name) {super(name);}
}

Master

package com.hspedu.poly_;public class Master {private String name;public Master(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}//父类的对象引用可以指向子类的对象本身//animal的编译类型是Animal,可以指向(接收) Animal 子类的对象//food编译类型是Food ,可以指向(接收) Food 子类的对象public void feed(Animal animal, Food food){System.out.println("主人" + name + "给" + animal.getName() + "喂" + food.getName());}//feed方法喂食物,每增加一种动物,就需要多写一个feed方法,十分麻烦
//    public void feed(Dog dog, Bone bone){
//        System.out.println("主人" + name + "给" + dog.getName() + "喂" + bone.getName());
//    }
//    public void feed(Cat cat, Fish fish){
//        System.out.println("主人" + name + "给" + cat.getName() + "喂" + fish.getName());
//    }
}

 main方法

package com.hspedu.poly_;public class Poly01 {public static void main(String[] args) {Master master1 = new Master("sunny");Dog dog = new Dog("大黄");Bone bone = new Bone("大棒骨~");master1.feed(dog,bone);Cat cat = new Cat("多多");Fish fish = new Fish("鲱鱼罐头~");System.out.println("=================");master1.feed(cat,fish);}
}

控制台输出

为了更好的验证对象的多态,增加了一个Animal的子类Rabbit,Food的子类Carrot

package com.hspedu.poly_;public class Rabbit extends Animal{public Rabbit(String name) {super(name);}
}
package com.hspedu.poly_;public class Carrot extends Food{public Carrot(String name) {super(name);}
}

 由于父类的对象引用可以指向子类的对象本身,所以可以直接在main方法内创建新对象

package com.hspedu.poly_;public class Poly01 {public static void main(String[] args) {Master master1 = new Master("sunny");Dog dog = new Dog("大黄");Bone bone = new Bone("大棒骨~");master1.feed(dog,bone);Cat cat = new Cat("多多");Fish fish = new Fish("鲱鱼罐头~");System.out.println("=================");master1.feed(cat,fish);Rabbit rabbit = new Rabbit("小白");Carrot carrot = new Carrot("胡萝卜");System.out.println("=================");master1.feed(rabbit,carrot);}
}

 五、向上转型

父类的对象引用指向子类的对象本身

Animal animal = new Dog();
package com.hspedu.poly_.detail_;public class TopBase {public void hello() {System.out.println("TopBase hello");}
}
package com.hspedu.poly_.detail_;public class Base extends TopBase{public void hi() {System.out.println("Base hi");}
}
package com.hspedu.poly_.detail_;public class Animal extends Base {String name = "动物";int age = 10;public void sleep(){System.out.println("睡");}public void run(){System.out.println("跑");}public void eat(){System.out.println("吃");}public void show(){System.out.println("hello,你好");}
}
package com.hspedu.poly_.detail_;public class Cat extends Animal{String color = "白色";public void eat(){//方法重写System.out.println("猫吃鱼");}public void catchMouse() {//Cat特有方法System.out.println("猫抓老鼠");}
}
package com.hspedu.poly_.detail_;public class PolyDetail {public static void main(String[] args) {//向上转型Animal animal = new Cat();animal.eat();//在编译阶段,能调用哪些成员,是由编译类型来决定的,// 编译类型是animal,可以访问从Object类到Animal类的所有方法,// 不能访问子类独有的方法// animal.catchMouse();Object obj = new Cat();//编译类型是Object,在编译阶段只能访问Object类的方法//向上转型调用方法的规则如下://(1)可以调用父类中的所有成员(需遵守访问权限)//(2)但是不能调用子类的特有的成员//(#)因为在编译阶段, 能调用哪些成员,是由编译类型来决定的//animal.catchMouse();错误//(4)最终运行效果看子类(运行类型)的具体实现, 即调用方法时, 按照从子类(运行类型)开始查找方法//,然后调用,规则跟前面学的方法调用规则一致。System.out.println("===================");animal.hello();//访问到TopBase类的hello()方法animal.hi();//访问到Base类的hi()方法animal.run();//访问到Animal类的run()方法animal.sleep();//访问到Animal类的sleep()方法animal.eat();//访问到Cat类的eat()方法animal.show();//访问到Animal类的show()方法}
}

六、向下转型

需要解决的问题:调用子类特有的方法

语法:子类类型 引用名 = (子类类型)父类引用名 

eg:Cat cat = (Cat)animal;

 在编译时没有错误,但是在运行时就会报错,出现以下错误

 

 类型转换异常

七、属性没有重写

属性只看编译类型以及比较运算符instanceof

package com.hspedu.poly_.detail_;public class PolyDetail02 {public static void main(String[] args) {AA aa = new BB();//属性没有重写之说System.out.println(aa.count);//属性看编译类型,输出10BB bb = new BB();System.out.println(bb.count);//20System.out.println(bb instanceof BB);System.out.println(bb instanceof AA);System.out.println(bb instanceof Object);//编译类型是AA,运行类型是BBAA aa1 = new BB();System.out.println(aa1 instanceof BB);System.out.println(aa1 instanceof AA);Object obj = new Object();System.out.println(obj instanceof AA);//falseString str = "hello";//System.out.println(str instanceof AA);//字符串和AA没有任何关系System.out.println(str instanceof Object);//true}
}
class AA{int count = 10;
}
class BB extends AA{int count = 20;
}

八、练习题

第一题

考察向上转型和向下转型的知识点,其中还有之前讲过的变量的强制类型转换

double d = 13.4;

long l = (long)d;

package com.hspedu.poly_.exercise_;public class PolyExercise01 {public static void main(String[] args) {double d = 13.4;//强制类型转换,变成13long l = (long)d;System.out.println(l);//输出13int in = 5;//boolean和int不能转换,所以报错//boolean b = (boolean)in;//向上转型,编译类型是Object,运行类型是String//父类Object的对象引用obj指向子类-String类的对象Object obj = "Hello";//向下转型,编译类型是String,运行类型是StringString objStr = (String)obj;//输出HelloSystem.out.println(objStr);//向上转型,编译类型Object,运行类型IntegerObject objPri = new Integer(5);//承接上句,父类引用objPri指向的是Integer类的对象//所以目标类型应该是Integer类,而不是String类//String str = (String)objPri;//编译没错,但是运行时会报错//向下转型,编译类型Integer,运行类型IntegerInteger str1 = (Integer)objPri;System.out.println(str1);//输出5}
}

 第二题

考察知识点:属性没有重写之说,对象的运行类型决定了调用哪个类中的方法(继承中的父类-子类)

package com.hspedu.poly_.exercise_;public class Base {int count = 10;public void display(){System.out.println(this.count);}
}

 

package com.hspedu.poly_.exercise_;public class Sub extends Base{int count = 20;public void display(){//方法重写System.out.println(this.count);}
}
package com.hspedu.poly_.exercise_;public class PolyExercise02 {public static void main(String[] args) {//编译类型是Sub,运行类型是SubSub s = new Sub();//属性是没有重写的,看编译类型,输出20System.out.println(s.count);//方法的调用由运行类型决定的,运行类型是Sub,输出20s.display();//向上转型,父类引用b指向子类Sub类的对象//编译类型是Base,运行类型是SubBase b = s;System.out.println(b == s);//指向同一对象本身,true//属性看编译类型,编译类型是Base,输出10System.out.println(b.count);//方法的调用由运行类型决定的,运行类型是Sub,输出20b.display();}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_75729.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

K_A13_002 基于STM32等单片机驱动干簧管传感器 串口与OLED0.96双显示

K_A13_002 基于STM32等单片机驱动干簧管传感器 串口与OLED0.96双显示一、资源说明二、基本参数参数引脚说明三、驱动说明模块工作原理:对应程序:四、部分代码说明1、接线引脚定义1.1、STC89C52RC干簧管传感器模块1.2、STM32F103C8T6干簧管传感器模块五、基础知识学习与相关资料…

Python+Yolov5跌倒检测 摔倒检测 人物目标行为 人体特征识别

PythonYolov5跌倒检测 摔倒检测 人物目标行为 人体特征识别如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01;前言这篇博客针对<<PythonYolov5跌倒摔倒人体特征识别>>编写代码&#xff0c;代码整洁&…

数据结构前提知识

数据结构数据结构 个体的存储个体关系的存储算法对存储数据的操作程序数据结构算法衡量算法的标准时间复杂度&#xff1a;注意不是程序执行的时间&#xff0c;因为一个程序执行的时间取决于软硬件环境&#xff0c;不同的机器&#xff0c;执行的速度不一样&#xff0c;配置好的…

CVPR 2023 接收结果出炉!再创历史新高!录用2360篇!(附10篇最新论文)

点击下方卡片&#xff0c;关注“CVer”公众号AI/CV重磅干货&#xff0c;第一时间送达点击进入—>【计算机视觉】微信技术交流群2023 年 2 月 28 日凌晨&#xff0c;CVPR 2023 顶会论文接收结果出炉&#xff01;这次没有先放出论文 ID List&#xff0c;而是直接 email 通知作…

最好的 QML 教程,让你的代码飞起来!

想必大家都知道&#xff0c;亮哥一直深耕于 CSDN&#xff0c;坚持了好很多年&#xff0c;目前为止&#xff0c;原创已经 500 多篇了&#xff0c;一路走来相当不易。当然了&#xff0c;中间有段时间比较忙&#xff0c;没怎么更新。就拿 QML 来说&#xff0c;最早的一篇文章还是 …

Linux内核崩溃 dump调试

内核-crash(崩溃)&#xff0c;oops消息&#xff0c;dump oops &#xff08;也称 panic&#xff09;&#xff0c;称程序运行崩溃&#xff0c;程序崩溃后会产生oops消息。 应用程序或内核线程的崩溃都会产生oops消息&#xff0c;通常发生oops时&#xff0c;系统不会发生死机&a…

中文预训练大模型—文心Ernie技术原理

文心Ernie技术原理 一、背景技术 Ernie是基于Bert模型进行改进&#xff0c;基本模型是Transformer&#xff0c;Bert完成的预训练任务是&#xff1a;完形填空&#xff08;通过基本语言单元掩码&#xff09;&#xff1b;上下句预测。 Bert模型的缺陷是&#xff1a;只能捕获局部…

【Spark分布式内存计算框架——Spark Streaming】9. 获取偏移量 应用案例:百度搜索风云榜(上)

4.4 获取偏移量 当SparkStreaming集成Kafka时&#xff0c;无论是Old Consumer API中Direct方式还是New Consumer API方式获取的数据&#xff0c;每批次的数据封装在KafkaRDD中&#xff0c;其中包含每条数据的元数据信息。 文档&#xff1a;http://spark.apache.org/docs/2.4.…

Linux系统介绍及熟悉Linux基础操作

一、什么是Liunx Linux&#xff0c;全称GNU/Linux&#xff0c;是一种免费使用和自由传播的类UNIX操作系统&#xff0c;其内核由林纳斯本纳第克特托瓦兹&#xff08;Linus Benedict Torvalds&#xff09;于1991年10月5日首次发布&#xff0c;它主要受到Minix和Unix思想的启发&am…

【图像处理】数字图像处理基础(分辨率,像素,显示...)

Table of Contents1.数字图像处理基础1.1 图像表示1.1.1 图像成像模型1.1.2 数字图像的表示a.图像采样b.图像灰度的量化c.算比特数1.2 分辨率1.2.1 空间分辨率1.2.2 灰度分辨率1.3 像素间的关系1.3.1 像素邻域a.4邻域b.4对角邻域c.8邻域1.3.2 像素邻接1.3.3 像素连通1.3.4 像素…

“速通“ 老生常谈的HashMap [实现原理源码解读]

&#x1f473;我亲爱的各位大佬们好&#x1f618;&#x1f618;&#x1f618; ♨️本篇文章记录的为 HashMap 实现原理&&源码解读 相关内容&#xff0c;适合在学Java的小白,帮助新手快速上手,也适合复习中&#xff0c;面试中的大佬&#x1f649;&#x1f649;&#x1f…

【Leedcode】栈和队列必备的面试题(第二期)

【Leedcode】栈和队列必备的面试题&#xff08;第二期&#xff09; 文章目录【Leedcode】栈和队列必备的面试题&#xff08;第二期&#xff09;一、题目&#xff08;用两个队列实现栈&#xff09;二、思路图解1.定义两个队列2.初始化两个队列3.往两个队列中放入数据4.两个队列出…

对账平台设计

背景 随着公司业务的蓬勃发展&#xff0c;交易履约清结算业务的复杂性也在不断的增高&#xff0c;资金以及各种数据的一致性和准确性也变得越发重要。 以交易链路为例&#xff0c;存在着如下一些潜在的不一致场景&#xff1a; 订单支付成功了&#xff0c;但是订单状态却还是“…

JVM方法区详解有这篇就够了

1、方法区在哪里《Java虚拟机规范》中明确说明&#xff1a;“尽管所有的方法区在逻辑上是属于堆的一部分&#xff0c;但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。”但对于HotSpotJVM而言&#xff0c;方法区还有一个别名叫做Non-Heap&#xff08;非堆&#xff09…

机械键盘不只有轴体的区别!键帽高度也有些学问

键盘键帽的学问有很多&#xff0c;上篇文章中&#xff0c;笔者和大家聊了键帽的材质和耐油污的问题。 除此之外&#xff0c;键帽的高度和字符的印刷方式也有不同&#xff0c;对于多数机械键盘来说&#xff0c;会发现每一列键帽的倾斜角度都略有不同&#xff0c;使用起来可以减少…

Android TV UI开发常用知识

导入依赖 Google官方为Android TV的UI开发提供了一系列的规范组件&#xff0c;在leanback的依赖库中&#xff0c;这里介绍一些常用的组件&#xff0c;使用前需要导入leanback库。 implementation androidx.leanback:leanback:$version常用的页面 这些Fragment有设计好的样式&…

3.ffmpeg命令行环境搭建、ffmpeg命令行初步了解

在上章,我们讲过: ffmpeg.exe: 主要用于转码或者剪切的应用程序, 也可以从url/现场音频/视频源抓取输入源ffplay.exe: 主要用于播放视频的应用程序,该应用程序源码是开源的,我们后面章节会去源码分析ffprobe.exe: 主要用于分析视频码流的应用程序, 可以获取媒体文件的详细信息,…

【Azure 架构师学习笔记】-Azure Data Factory (4)-触发器详解-事件触发器

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Data Factory】系列。 接上文【Azure 架构师学习笔记】-Azure Data Factory (3)-触发器详解-翻转窗口 前言 事件触发指的是存储事件&#xff0c;所以在新版的ADF 中&#xff0c;已经明确了是“存储事件”&#xff0c;…

【C语言】结构体进阶

一、结构体 1. 结构体的声明 &#xff08;1&#xff09; 结构的基础知识 结构是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量。&#xff08;2&#xff09;结构的声明 struct tag {member-list; }variable-list;例如描述一个学生&#x…

【SPSS】两配对样本T检验分析详细操作教程(附案例实战)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…