前两章已经给咱们预习了封装和继承,咱们这一章开始复习多态
目录
多态的定义:
去完成同一个行为,当不同的对象去完成时会产生不同的状态
举个栗子:打印可以用彩色打印机打印,也可以用黑白打印机打印,这两个都可以完成打印这个行为,并且打印出彩色的照片或黑白的照片
多态的实现需要什么条件呢?
1,必须在继承条件下
2,子类必须要对父类中的方法进行重写
3,通过父类的引用调用重写的方法
需要了解多态那么要先理解一下什么是动态绑定
动态绑定
产生动态绑定的条件
- 向上转型
- 重写
- 通过父类的引用调用这个父类和子类重写的方法
我们会惊奇的发现,动态绑定的条件和多态的条件好像是一样的!!
动态绑定的定义:
在编译的时候还是在用的是父类的方法,但是运行的时候用的是子类的方法
可能这句话读起来有点难理解,那么我们拿代码给大家展示一下就能好理解一点啦
class Animal{
public String name;
public void eat(){
System.out.println(name+"正在吃饭");
}
}
class Dog extends Animal{
public void wolf(){
System.out.println(name+"正在汪汪叫!!!!");
}
@Override
public void eat(){
System.out.println(name +"正在吃狗粮");
}
}
class Bird extends Animal{
public void wing(){
System.out.println(name+"有翅膀!!!");
}
@Override
public void eat(){
System.out.println(name+"正在吃鸟粮!!");
}
}
运行结果
我们可能会疑惑,为什么会产生这个结果?它不是调用父类中的eat()方法吗?
那我们可以看一下它的字节码文件
如何查看字节码文件
1,点击手表右键,点击show in Explorer
2,点击目录中的out
然后进入cmd
输入javap -c +文件名称
我们可以 通过上面查看编译完成的字节码文件,可以得知,编译的时候,调用父类的eat()
所以我们可以得出动态绑定就是:在编译的时候还是在用的是父类的方法,但是运行的时候用的是子类的方法
那么有动态绑定就会有静态绑定
静态绑定:是在编译的时候已经知道调用那个方法了,比如重载
我们可以发现上面代码有一个
Animal animal1 = new Dog();
这个就称为向上转型
向上转型:
上和下怎么区分呢?
上:父类;下:子类
那么向上转型就是把子类给父类就称为向上转型
理论上来说,等号两边是数据类型必须一样,赋值会出错,但是在继承关系上就不会报错
当发生向上转型的之后,此时通过的引用只能访问父类自己的成员,不能访问到子类的成员
向上转型有三种表现方式:
1,直接赋值
2,方法传参
3,方法返回
有向上转型就会有向下转型
向下转型
向下转型就是将父类的类型给子类
向下转型非常不安全!!!!
因为你不能确保所有的动物都是鸟
如何解决这个异常呢?
引用一个关键字
instanceof
可以来进行一个判断,判断一个引用是不是真的引用了某个对象
重写
重写需要满足三个条件
- 方法名称相同
- 返回值相同
- 参数列表相同
如上所表示的,这三个方法就构成了重写
重写需要注意的点:
- private修饰的方法不能被重写
- static修饰的方法不能被重写
- 子类的限定修饰权限,要大于等于父类的修饰权限
- 被final修饰的方法是不能被重写的,此时的方法被称为密封方法或者终态方法
修饰限定符大小:private < 默认方法 < protect < public
避免在构造方法中调用重写的方法
注意:
当在父类的构造方法当中,去调用父类和子类重写的方法的时候,会调用子类的
重写和重载的区别:
重写的返回值,参数列表,方法名称都必须相同,但是重载,方法名称必须相同,参数列表和返回值都可以不同;访问修饰限定符的话,重写是子类必须大于或等于父类的修饰限定符.但是重载不做要求
多态的优点缺点:
优点:
1,能够降低代码的"圈复杂度"
2,可扩展能力强
缺点:
代码的运行效率降低