通过超类引用变量访问子类成员

时间:2017-12-20 01:22:05

标签: java inheritance method-overriding

我正在阅读一本Java教科书并遇到了疑问。 可以为超类的引用变量分配对从该超类派生的任何子类的对象的引用。但是,当将子类对象的引用分配给超类引用变量时,您将只能访问超类定义的对象的那些部分。 例如:

class X {
    int a;
    X(int i) {
        a = i; 
    }
}

class Y extends X {
    int b;
    Y(int i, int j) {
        super(j);
        b = i;
    }
}

class SupSubRef {
    public static void main(String args[]) {
        X x = new X(10);
        X x2;
        Y y = new Y(5, 6);
        x2 = x; // OK, both of same type
        System.out.println("x2.a: " + x2.a);
        x2 = y; // still Ok because Y is derived from X
        System.out.println("x2.a: " + x2.a);
        // X references know only about X members
        x2.a = 19; // OK
        // x2.b = 27; // Error, X doesn't have a b member
    }
}

因此,在上面的例子中,x2(超类类型的变量)可以引用派生类的对象,它不能访问子类特定成员。但是,在关于方法重写的讨论中,显示了超类引用变量对重写方法的调用可以解析为子类方法。但是子类方法没有在超类中定义,所以这不是一个矛盾,超类引用变量如何能够访问子类特定的方法?例如:

class Sup {
    void who() {
        System.out.println("who() in Sup");
    }
}
class Sub1 extends Sup {
    void who() {
        System.out.println("who() in Sub1");
    }
}
class Sub2 extends Sup {
     void who() {
         System.out.println("who() in Sub2");
     }
}

class DynDispDemo {
    public static void main(String args[]) {
        Sup superOb = new Sup();
        Sub1 subOb1 = new Sub1();
        Sub2 subOb2 = new Sub2();
        Sup supRef;
        supRef = superOb;
        supRef.who();
        supRef = subOb1;
        supRef.who();
        supRef = subOb2;
        supRef.who();
    }
}

程序的输出如下所示:

who() in Sup
who() in Sub1
who() in Sub2

那么supRef如何能够访问子类对象中的who方法呢?

1 个答案:

答案 0 :(得分:1)

当教科书说您无法使用x2访问特定于子类的成员时,这意味着您无法在编译时访问它们

到编译器。 x2的类型为X(虽然它在运行时中的类型为Y),因此当编译器看到您尝试访问{{1}中定义的内容时它突出并说“Y中没有定义。你不能这样做!”

但是,我们都知道在运行时,X存储对x2对象的引用。在运行时,您可以确实使用Y访问Y中定义的成员。你可以用反射证明这一点。

在运行时,x2的类型为x2,因此显然会调用Y的实现。