一、向上转型(子类引用给父类)
在之前的例子中,我们写了
Bird bird = new Bird ("圈圈");
也可以写成这样
Bird bird = new Bird ("圈圈");
Animal bird2 = new Bird;
或者这样
Animal bird2 = new Bird("圈圈");
此时 bird2 是一个父类 (Animal) 的引用, 指向一个子类 (Bird) 的实例. 这种写法称为 向上转型.
向上转型发生的时机:
- 直接赋值(上面讲的赋值就是直接赋值)
- 方法传参
- 方法返回
方法传参
class Bird {
public Bird(String name) {
this.name = name;
}
public class Test {
public static void main(String[] args) {
Bird bird = new Bird("圈圈");
feed(bird);
}
public static void feed(Animal animal) {
animal.eat("谷子");
}
}
// 执行结果
圈圈正在吃谷子
方法返回
public class Test {
public static void main(String[] args) {
Animal animal = findMyAnimal();
}
public static Animal findMyAnimal() {
Bird bird = new Bird("圆圆");
return bird;
}
}
上述代码findMyAnimal方法返回的是一个Animal类型的引用,但是实际上却是对应到了Bird的实例
二、动态绑定(运行时绑定)
当子类和父类中出现同名方法的时候, 再去调用会出现什么情况呢?
接下来看下面的代码吧
//定义动物类
class Animal{
protected String name;
public Animal(String name){
this.name=name;
}
public void eat(String food){
System.out.println(this.name+"animal"+food);
}
}
class Bird extends Animal{
public Bird(String name) {
super(name);
}
@Override
public void eat(String food) { //子类重写eat方法
System.out.println(this.name+"bird"+food);
}
}
public class Test {
public static void main(String[] args) {
Animal animal1 = new Animal("小小");
animal1.eat("豆子");
Animal animal2 = new Bird("大大");
animal2.eat("豆子");
}
}
//打印结果
小小animal豆子
大大bird豆子
此时我们发现
- animal1 和 animal2 虽然都是 Animal 类型的引用, 但是 animal1 指向 Animal 类型的实例, animal2 指向 Bird 类型的实例.
- 针对 animal1 和 animal2 分别调用 eat 方法, 发现 animal1.eat() 实际调用了父类的方法, 而 animal2.eat() 实际调用了子类的方法
因此
,
在
Java
中
,
调用某个类的方法
,
究竟执行了哪段代码
(
是父类方法的代码还是子类方法的代码
) ,
要看究竟这个引
用指向的是父类对象还是子类对象
.
这个过程是程序运行时决定的
(
而不是编译期
),
因此称为
动态绑定
发生动态(运行时绑定)条件:
①继承(父类要引用子类)
②通过父类的引用调用子类和父类同名的覆盖方法
使用多态的好处是什么
?
1)
类调用者对类的使用成本进一步降低
.
封装是让类的调用者不需要知道类的实现细节
.
多态能让类的调用者连这个类的类型是什么都不必知道
,
只需要知道这个对象具有某个方法即可
.
因此
,
多态可以理解成是封装的更进一步
,
让类调用者对类的使用成本进一步降低
2)
能够降低代码的
"
圈复杂度
"。
什么是圈复杂度?
圈复杂度是描述一段代码复杂程度的方式。一段代码如果平铺直叙,那么就容易理解,而如果有很多的条件分支或者循环语句,就认为理解起来复杂
计算一段代码中条件语句和循环语句出现的个数,这个个数就称为“圈复杂度”。若一个方法的圈复杂度太高,就需要考虑重构
圈复杂度是描述一段代码复杂程度的方式。一段代码如果平铺直叙,那么就容易理解,而如果有很多的条件分支或者循环语句,就认为理解起来复杂
计算一段代码中条件语句和循环语句出现的个数,这个个数就称为“圈复杂度”。若一个方法的圈复杂度太高,就需要考虑重构
3)
可扩展能力更强
.