继承是面向对象的三大特征(封装、继承和多态)之一,也是Java语言的重要特性。
那么,继承父类的成员变量和继承父类的方法有什么区别吗?答案是肯定的。有的人甚至都不知道这个问题的存在。
继承成员变量和继承方法的区别:
可能大家都认同 “当子类继承父类时,子类会获得父类中定义的成员变量和方法,当访问权限允许的情况下,子类可以直接访问父类的变量和方法”的看法。这种观点其实稍显笼统,因为java继承中对成员变量和方法的处理是不同的。示例如下:
class Base{
int count=2;
public void display(){
System.out.println(this.count);
}
}
public class Derived extends Base{
int count=20;
@Override
public void display() {
System.out.println(this.count);
}
public static void main(String[] args) {
//父类引用指向子类对象
Base bd=new Derived(); //注释1
System.out.println(bd.count);
bd.display();
}
}
输出结果:
-------------------------------------
2
20
-------------------------------------
如果你刚刚稍微认真分析了代码,你可能会发现你的预计输出跟实际输出是不同的。很可能你会说“不对呀,bd不是指向子类Derived的对象吗?结果不应该是20吗?”
其实原因是这样的:
首先应该知道声明时类型、运行时类型这两个概念。前者是说在声明一个引用变量时用到的类型,后者是指在实际运行中的类型。可能会比较抽象。简单来说对于Base bd=new Derived();
Base就是bd的声明时类型,Derived就是bd的运行时类型。
一个简单却重要的结论是:如果子类重写了父类的方法,那么就会覆盖父类中被重写的方法,这时,指向子类对象的引用调用这些父子类都有的方法无论声明时类型是其父类还是自身,调用的都是子类中重写后的方法,这叫做覆盖。而父类的成员变量却不会被子类中同名的成员变量所覆盖,当这些同名的实例变量被引用变量访问时,其返回值取决于引用的声明时类型。
例如本例中bd的声明时类型是Base,这时访问父子类同名的实例变量count的返回值就是Base类中的count值。
bd.display()当然调用的就是运行时类型Derived类中的(如果该方法在子类中被重写的话,否则调用父类中的)。
转自: