隐藏与覆盖

几乎完全借鉴https://www.cnblogs.com/shakinghead/p/7445831.html

当子类继承父类时,除了继承父类所有的成员变量和成员方法之外,还可以声明自己的成员变量和成员方法。那么,如果父类和子类的成员变量和方法同名会发生什么?我们声明一个静态类型是父类,动态类型是子类的引用:

A a=new B();

对于成员变量(不管是静态还是非静态)都只进行静态绑定,所以JVM的绑定结果会是:直接访问静态类型中的成员变量,也就是父类的成员变量。对于静态方法,也是只进行静态绑定,所以JVM会通过引用的静态类型,来进行绑定,结果为:直接调用父类中的静态方法。

子类继承父类后,父类的属性和静态方法并没有被子类抹去,通过相应的引用可以访问的到。但是在子类中不能显示地看到,这种情况就称为隐藏。

对于非静态方法,会进行动态绑定,JVM检查出引用father的动态类型,绑定结果为:调用子类中的静态方法。

子类继承父类后,父类的非静态方法被子类重写后覆盖上去,通过相应的引用也访问不到了(除非创建父类的对象来调用)。这种情况称为覆盖。

子类继承父类后:父类的成员变量只会被隐藏,而且支持交叉隐藏(比如静态变量被非静态变量隐藏)。父类的静态方法只会被静态方法隐藏,不支持交叉隐藏。父类的非静态方法会被覆盖,但是不能交叉覆盖。继承体现了同一个基类的不同子类之间的耦合性,而多态则是消除这种耦合体现这些类型之间的对于方法的差异性。前期绑定导致的后果就是隐藏;后期绑定导致的后果就是覆盖,继而实现多态。属性和静态方法(还有final、private)都是静态绑定,其余的实例方法是动态绑定。所以,只有实例方法可以体现多态性,域(属性)和静态方法体现不出多态。

class A {

    int a = 1;
    int b = 2;

    public double test(){
        return a;
    }
}

class B extends A{

    double a = 1.0;
    char b = 'b';

    public double test(){
        System.out.println("In B, super.a = "+super.a);
        return a;
    }
}

public  class  Main{
    public static void main(String []args){
        A a = new A();
        B b = new B();
        System.out.println(b.test()+" a = "+b.a);
        System.out.println(a.test()+" a = "+a.a);

    }
}

猜你喜欢

转载自blog.csdn.net/qq_41722524/article/details/87452407