Skip to content

多态

Java允许具有继承关系的父子类型之间的类型转换

向上转型和向下转型

  • 向上转型:自动

子类型的对象可以赋值给父类型的引用

java
Animal a = new Dog();
  • 向下转型:强制

父类型的引用可以转换为子类型的引用,但是需要添加强制类型转换符

java
Dog d = (Dog) a;

多态

多态指的是多种形态,编译阶段一个形态,运行阶段另一种形态,因此叫做多态

java
fclass Animal {
    public void speak() {
        System.out.println("动物发出声音");
    }
}

class Dog extends Animal {
    @Override
    public void speak() {
        System.out.println("狗叫");
    }
}

class Cat extends Animal {
    @Override
    public void speak() {
        System.out.println("猫叫");
    }
}

public class Test {
    public static void main(String[] args) {

        Animal a1 = new Dog();
        Animal a2 = new Cat();

        a1.speak();
        a2.speak();
    }
}

程序分为编译阶段和运行阶段

  • 编译阶段:编译器只知道a1是Animal类型,因此去Animal类中寻找speak方法,找到之后,绑定成功,编译通过。这个过程称为静态绑定
  • 运行阶段:运行时和JVM堆内存中真实Java对象有关,运行时a1是Dog实例,所以运行时会自动调用真实对象的speak方法,这个过程称为动态绑定

ClassCastException

向下转型时,使用不当容易发生类型转换异常:ClassCastException。我们可以使用instanceof运算符在运行阶段进行判断避免发生ClassCastException

对象 instanceof 类名

返回值是 boolean

  • true:对象是该类型或其子类型
  • false:不是
java
class Animal {}

class Dog extends Animal {
    void bark() {
        System.out.println("狗叫");
    }
}

class Cat extends Animal {}

public class Test {

    public static void main(String[] args) {

        Animal a = new Dog();

        if (a instanceof Dog) {
            Dog d = (Dog) a;
            d.bark();
        }
    }
}

多态实现 OCP

java
 class Pet {

    public  void speak(){
        System.out.println("宠物在叫");
    }

}
java
class Dog extends Pet {

    @Override
    public void speak() {
        System.out.println("狗在叫");
    }

}
java
class Cat extends Pet {

    @Override
    public void speak() {
        System.out.println("猫在叫");
    }

}
java
class Person {

    public void play(Pet pet) {
        pet.speak();
    }

}

Person只依赖Pet,而不依赖Cat,Dog。更换宠物时,我们不需要修改旧代码:Person。只需要新增一个类即可:

java
class Bird extends Pet {

    @Override
    public void speak() {
        System.out.println("鸟在叫");
    }

}

这就是:对扩展开放对修改关闭

如果一个功能的修改需要修改源代码才能实现,则说明功能原来的设计是失败的。