多态
1216字约4分钟
2024-12-02
多态
多态就是多种形态
重载和重写的原理就是多态,它们是方法多态,通过参数的不同调用不同的方法
多态例子1:
父类
// 编译类型
public class Animal {
public void info() {
System.out.println("叫");
}
}
子类
// 运行类型
public class Cat extends Animal {
public Cat() {
System.out.println("小猫咪");
}
}
public class Dog extends Animal {
public Dog(String name) {
System.out.println("修狗");
}
}
运行
public class Demo01 {
public static void main(String[] args) {
// 构成多态的前提是 运行类型 必须是 编译类型 的子类
Animal animal = new Cat();
animal = new Dog("修狗");
}
}
多态的细节
要调用构造器则需要自己new一个,调用构造器是在创建对象的时候才调用的
向上转型
向上转型 : 父类的引用指向子类的对象
语法:
父类类型 引用名 = new 子类类型();
编译类型(父类)在等号的左边,运行类型(子类)在等号的右边
构成多态的前提是 运行类型 必须是 编译类型 的子类,也就说它们是继承关系
向上转型可以调用父类中的所有成员方法以及属性(但要遵守访问权限),但子类中的属性或则独有的方法则不能被调用
不能调用子类特有的方法(也就是只有子类中才有的方法而父类没有)
调用时会优先查找 运行类型(子类) 中是否有该方法,如果没有则到编译类型(父类)中去查找,类似继承
调用的方法是父类和子类共有的,或则父类独有的;子类独有的方法不能被调用
最终的实现效果要看子类的的具体实现(如果子类和父类中有共有的方法,那么调用该类的时候会优先调用子类中的方法,所以子类中的方法发生改变则会影响最终的运行结果)
属性没有重写的说法,属性的值看编译类型(也就是说只能调用编译类型里面的属性,运行类型里面的属性则无法被调用),如果想调用子类中的属性,则可以使用向下转型或则直接创建该类型的对象即可调用该子类中的属性
class A { String name = "A类型"; } class B extends A { String name = "B类型"; } public class info() { public static void main(String[] args) { // 直接调用该对象 // 调用父类中的属性 A a = new A(); System.out.println(a.name); // 调用子类中的属性 B b = new B(); System.out.println(b.name); // 使用多态调用 // 调用父类中的属性 A a1 = new B(); // 向上转型 System.out.println(a1.name); // 调用子类中的属性 B b1 = (B) A; // 向下转型 System.out.println(b1.name); } }
向下转型
向下转型可以调用子类中独有的方法和属性
向下转型优先调用本类(子类)中的属性和方法
语法:
子类类型 引用名 = (子类类型) 父类的引用;
要求 父类和子类必须是继承关系,这样才可以使用向下转型,向上转型也是一样的;也就是说两个类型必须是继承关系才可以使用向上转型或则向下转型
编译类型在等号的左边,运行类型在等号的右边
所以在创建向下类型的时候要先创建向上类型,然后在调用父类的引用名
调用时会优先查找 编译类型(子类) 中是否有该方法,如果没有则到父类中去查找,类似继承
向下转型可以调用 子类和父类 中的普通方法和属性(但是不能调用构造器)
如果父类指向子类1,那个父类就可以强制转换为子类1;父类没有指向子类2,那么父类就不能强制转换为子类2
// 父类指向 Cat Animal animal = new Cat(); // 父类可以被强制转换为 Cat Cat cat = (Cat) animal; // 因为父类没有指向 Dog,所以父类就不能强制转换为 Dog,所以这里编译会出错(会报类异常) Dog dog = (Dog) animal;
// 父类指向 Cat Animal animal = new Cat(); // 父类可以被强制转换为 Cat Cat cat = (Cat) animal; // 现在父类就指向Dog了,这样既不影响到上面Cat的代码,也不影响下面Dog的代码 animal = new Dog(); // 现在父类可以强制转换为 Dog 了 Dog dog = (Dog) animal;
调用子类简写
// Student s = (Student) p[i]; // s.Stu(); // 下面这行代码就是上面两行代码的缩写 ((Student) p[i]).Stu();