一、多态前言
1.为什么要使用多态
Java中使用多态的主要目的是提高代码的可重用性和扩展性,使得代码更加灵活和易于维护。通过多态,我们可以将不同的对象看做是同一种类型,从而使得我们可以使用同一种接口来操作这些对象,而不必关心具体的实现细节。
2.多态概念
当父类的引用所指向的子类对象引用指向的对象不一样时。调用重写的方法,所表现出来的行为是不一样的,我们把这种思想叫做多态。上面所说的可能大家会觉得有点抽象,看到后面就懂了。
多态的基础是动态绑定,所以要了解多态前提我们还要了解动态绑定。
要想实现动态绑定,需要满足以上几个条件:
1.要发生向上转型
2.要发生重写
3.使用父类对象的引用去调用重写方法
完成了这三部分,就会发生动态绑定,而在这里,出现了重写以及向上转型这些概念。所以我们得先了解它们才能去了解动态绑定。进而了解多态。
二、重写
1.重写的概念
方法重写的规则:
1.子类在重写父类的方法时,必须与父类方法原型一致:即返回值、方法名、参数列表要完全一致
2.被重写的方法的访问修饰限定符在子类中要大于等于父类的。
3.父类中被static或private或final修饰的方法以及构造方法都不能被重写。
4.在子类中重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验。
2.重写的作用
三、向上转型
语法格式:父类类型 对象名 = new 子类类型()
Animal animal = Dog();
Dog dog = new Dog();
Animal animal = dog;//该代码发生了向上转换,将Dog对象转换为Animal类型
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
void sound() {
System.out.println("Dog barks");
}
void fetch() {
System.out.println("Dog fetches a ball");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog(); // 创建Dog对象
Animal animal = dog; // 向上转型,将Dog对象转换为Animal类型
animal.sound();//调用子类的覆盖方法
// animal.fetch(); // 编译错误,因为Animal类中没有fetch方法
}
}
// 输出: Dog barks
通过以上代码发现一个问题,不能调用到子类特有的方法(因为编译时调用的是父类的方法),我们可以通过向下转型来调用到子类特有的方法(后面介绍)
静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表函数重载。
动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法。当发生重写时,通过父类调用该方法时会发生动态绑定。
见以下代码
public class TestAnimal {
// 2. 方法传参:形参为父类型引用,可以接收任意子类的对象
public static void eatFood(Animal a){ //因为主方法的原因使用静态方法
a.eat(); //方法传参向上转型
}
// 3. 作返回值:返回任意子类对象的实例
public static Animal buyAnimal(String var){
return new Dog();
}