class Person{
String name = "person";
}
class Son extends Person {
String name = "son";
}
public class Test {
public static void main(String[] args){
Person p = new Son();
System.out.println(p.name); //son
}
}
因为Person p = new Son();
就是把子类转型为父类
子类转型为父类的规则:
1. 只能调用父类的属性
2. 只能调用父类未被复写的方法
3. 只能调用被子类复写的方法
----------------------------------------------------------------------------------------------------------------
而属性并不能被复写,只是重名了。对此我们可以验证一下:
在父类添加一个fun(){System.out.println("父类方法");}
在子类复写方法fun(){System.out.println("子类方法");}
然后在主方法中:
Son p2 = new Son();
p2.run(); //子类直接调用fun方法
((Person )p2).run(); //转成父类后调用fun方法
System.out.println(p2.name); //子类直接调用name属性
System.out.println(((Person )p2).name); //转成父类后调用name属性
结果输出是:
子类方法
子类方法 <-------由于方法被子类覆盖了所以即使转型成父类也同样是调用被复写的方法
son
person <-------虽然属性被重名了,但并不能覆盖掉父类的属性!!
通俗的说就是:父类中的name属性属于父类的,子类的name属性属于子类的。
所以子类转型为父类后调用的name是父类中name属性,且也只能调用父类的属性。
----------------------------------------------------------------------------------------------------------------
变量是静态绑定,方法是动态绑定。静态绑定就是变量本身什么类型,就用哪个里面的。例如,你的p.name的p是Person类型,那么name就是Person类中的name。而如果是动态绑定,那么会从本身类型开始向超类型查找。如果name是方法,那么用于p是Son类的一个对象,所以会从Son开始找name方法,如果找不到再到父类中找。
网友评论