面向对象特征之三:多态性(polymorphism)
- 1.理解多态性:可以理解为一个事物的多种形态。
- 2.何为多态性:
- 对象的多态性,父类的引用指向子类的对象
- 3.多态使用:虚拟方法调用
- 有了对象的多态性以后,在编译器只能调用父类中声明的方法,单在运行期实际执行的是子类重写父类的方法
- 总结:编译看左边,执行看右边
- 4.多态性使用前提:
类的继承关系
方法的重写 - 5.对象的多态性,只适用于方法,不适用于属性(编译和执行都只看左边)
- 有了对象的多态性以后,内存中实际是加载了子类特有的属性和方法,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。
- 如何才能使用子类特有的属性和方法?
- 向下转型:使用强制类型转换符
Man p1 = (Man)p2;
- *使用强转时可能出现ClassCastException的异常
instanceof
a instanceof A:判断对象a是否是类A的实例。如果是,返回true:如果不是,返回false。
- 为了避免在向下转型时出现ClassCastException的异常,在向下转型之前,先进行instanceof的判断,一旦返回true,进行向下转型,如果返回false,不进行向下转型。
- 如果a instanceof A返回true,a instanceof B也返回ture,则B是A的父类
if(p2 insatnceof Man){
Man m2 = (Man)p2;
m2.earnMoney();
Sout("Man");
}
//true
if(p2 insatnceof Woman){
Man m2 = (Man)p2;
m2.earnMoney();
Sout("Woman");
}
//false
if(p2 instanceof Person){
sout("Person");
}
//true
if(p2 instanceof Object){
sout("Object");
}
//true
问题一:编译时通过,运行时不通过
Person p3 = new Woman();
Man m3 = (Man)p3;
Person p4 = new Person();
Man m4 = (Man)p4;
问题二:编译通过,运行也通过
Object obj = new Woman();
Person p = (Person)obj;
问题三:编译不过
Man m5 = new Woman();
注意:
-
若子类重写了父类方法,意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统不可能吧父类的方法转移到子类中。编译看坐边,运行看右边。
-
对于实例变量则不存在这种现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量:编译运行都看左便。
/*
- 建立InstanceTest类,在类中定义方法method(Person e)
- */
public class InstanceTest {
public static void main(String[] args) {
InstanceTest test = new InstanceTest();
test.method(new Student());
}
public void method(Person e){
//虚拟方法调用
String info = e.getInfo();
System.out.println(info);
if(e instanceof Graduate){
System.out.println("a graduate student");
}else if(e instanceof Student){
System.out.println("a student");
}else if(e instanceof Person){
System.out.println("a person");
}
}
}
class Person{
protected String name = "person";
protected int age = 50;
public String getInfo(){
return "Name: " + name + "\n" + "age: " + age;
}
}
class Student extends Person{
protected String school = "pku";
public String getInfo(){
return "Name: " + name + "\n" + "age: " + age + "\n" + "school:" + school;
}
}
class Graduate extends Student{
public String major = "IT";
public String getInfo(){
return "Name: " + name + "\n" + "age: " + age + "\n" + "school:" + school + "\n" + "major: " + major;
}
}