在创建对象的时候大家一般是这样创建的:
A a = new A(); //表示创建了A类的一个对象实例a
但是当在有父类和子类等继承关系的时候创建的对象时,情况就变得复杂了一些,例如:
父类 对象1 = new 子类();
父类 对象2 = new 父类();
子类 对象3 = new 子类();
对象1、2、3分别可以调用父类和子类中的哪些方法是合法的呢?这需要进行分析。
此外,这还涉及到一定的向下转型的知识。
结论
(编译类型就是等号左边的类,运行类型就是右边的,我反正是这么记忆的)
A a = new B() //编译类型为A,运行类型为B
1. 编译类型子类,运行类型子类:
正常的子类(public类型),可以运行 自己的方法 和 继承的父类的方法。
子类在访问重写方法(父类子类名称一样的方法)时,从子类开始找起来运行。
2. 编译类型父类,运行类型子类:
父类编译类型对象可以运行自己的(父类)方法和子类的重写方法。
但是不可以运行子类的特有方法,找不到,如果非要运行,那么需要向下转型。
3. 此外:
访问“方法”的时候从运行类型的类找起,也就是说如果子类重写了方法,上文“情况2”的对象调用方法时,输出的是从运行类型的子类开始找到的方法。
与之相对的,访问“属性”的时候直接看编译类型。编译类型是哪个类,就是指的哪个类里的属性。
father a = new son();
a.重写方法(); //调用的是子类son的方法
a.属性; //调用的是父类father的属性
写的不错,但今天做一下补充,如果父类的属性是private(或者default)修饰,那么子类里编译类型是父类的对象也还是无法访问到的!
向下转型:
针对上文的情况2,该对象无法运行子类的独有方法时,可以采用向下转型的方法来运行。
格式:
子类类型 引用名 = (子类类型)父类引用;
例如:Animal父类,dog子类
Animal animal = new dog(); dog dogyin = (dog) animal; //向下转型
然后dogyin
这个对象就可以调用dog子类特有方法了。
也可以直接:
((dog)animal).子类特殊方法
来进行调用。
注意:
转型其实并不会改变animal
的指向,而是等同于再创造一个dogyin
指向dog
罢了。
也就是说,animal仍然指向new出来的dog()