007-面向对象编程-多态
面向对象编程-多态
认识多态
-
多态是在继承/实现情况下的一种现象,表现为:对象多态,行为多态。
-
对象多态:不同动物有不同特征
Animal a1 = new Wolf(); Animal a2 = new Tortoise();
- 合理性:小范围的可以赋给大范围的
-
行为多态:乌龟老虎都能跑,但一个人快,一个人慢
-
对于方法,编译(写代码时)看左,类型看右
-
// 创建对象时 Animal a1 = new Wolf(); a1.run(); // 编译器先确定左边的父类Animal里有没有run()方法,有就不报错 // 但运行时会看右边对象的方法是什么内容,执行右边对象的方法而不是父类方法
-
-
对于成员变量,编译(写代码时)看左,运行也看左
- 变量不强调多态性
-
-
-
多态的前提:
- 有继承/实现关系
- 存在父类引用子类对象
- 存在方法重写
多态下的好处和存在的问题
-
使用多态的好处
-
在多态形式下,右边对象时解耦合的,更便于扩展和维护
- 解耦合:可以拆解组合,例如一个教师对象,如果废除这个对象可以直接改为学生对象,他们都属于人类对象,不需要改其他代码
-
定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强、更便利
-
比如动物类为父类,乌龟和狼是子类,那么一个函数形参可以把参数类型改成动物,这样乌龟类型和狼类型都能传进来。
-
-
-
多态下会产生一个问题:
-
多态下不能使用子类独有的功能
-
// 创建对象时 Animal a1 = new Tortoise(); a1.run();// 可以,因为Animal中有run()方法 a1.shrinkHead();// 不可以,因为Animal中没有shrinkHead()方法,shrinkHead()方法Tortoise中专有的,编译器编译的时候看左边,则会报错
-
-
多态下的类型转换(解决多态下不能使用子类独有的功能问题)
-
自动类型转换:
// 自动类型转换 // 父类 变量名 = new 子类() People p = new Teacher();
-
强制类型转换:
// 先创建变量同自动类型转换 People p = new Teacher(); // 强制类型转换 // 子类 变量名 = (子类)父类变量 People p = new Teacher(); Teacher t = (Teacher)p;
-
强制类型转换的一个注意事项
-
存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错
-
运行时,如果发现对象的真实类型与强转后的类型不同,就会报类型转换异常(ClassCastException)的错误出来
-
比如Wolf和Tortoise都继承自Animal,把Tortoise转换成Wolf不会在编译时报错,但运行时会出现ClassCastException异常
-
强转前,Java建议:
-
使用instanceof关键字,判断当前对象的真实类型,再进行强转
-
例如:
Animal a1 = new Tortoise(); if(a1 instanceof Wolf) { Wolf w1 = (Wolf)a1; }
-
场景:父类形参不能确定传入的是什么数据,那么就需要这个判断条件来判断到底把这个Animal转换成Wolf还是Tortoise
-
-
杂项(lombok、...)
- lombok技术可以实现为类自动添加getter setter方法、无参构造器、toString方法等
- 只需要导入lombok包,然后在类前加上
@Data
注解即可 - 如果需要有参构造器,在
@Data
下面再加一行@AllArgsConstructor
- 首次使用lombok前,需要在IDEA的 文件->设置 里搜注解(annotation processing),点击开启“启用注解处理(Enable annotation processing)”
- 只需要导入lombok包,然后在类前加上