多态
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("鸟在叫");
}
}这就是:对扩展开放,对修改关闭
如果一个功能的修改需要修改源代码才能实现,则说明功能原来的设计是失败的。
