Java继承:向上转换子类

时间:2018-02-21 14:34:19

标签: java inheritance casting upcasting

我已经阅读过文档和其他问题,但有些情况会让我感到很困惑。

我有这个例子,虽然经过一番思考后前3个案例非常简单,但最后4个让我感到困惑。

显然有一些关于铸造的东西,我不明白。

class A {
    public static   void p (Object o)   { System.out.println(o); }
    public          void m1 (A a)       { p("m1(A) in A"); }
    public          void m1 ()          { m1(new B());}
    public          void m2 (A a)       { p("m2(A) in A");}
    public          void m2 ()          { m2(this);}
    public          void m3 (B b)       { m2(this); }
}

class B extends A {
    public          void m1 (B b)       { p("m1(B) in B");}
    public          void m2 (A a)       { p("m2(A) in B");}
    public          void m2 (B b)       { p("m2(B) in B");}
    public          void m3 (B b)       { super.m1(b);}
}

public class Main {
    public static void main(String[] args) {
        A a = new B(); // Instance of class B casted to A
        B b = new B(); // Instance of class B

        // 1. prints "m1(A) in A"
        b.m1();

        // 2. prints "m2(A) in B"
        b.m2();

        // 3. prints "m2(A) in B"
        a.m2();

        // 4. prints "m1(A) in A"
        a.m3((B)a);
    }
}

示例1:

我希望在这里打印m1(B) in B

B继承A,由于没有B.m1(),因此会调用A.m1()来调用m1(B)。由于我们是从B调用的,为什么它会调用A.m1(B)而不调用B.m1(B)

我希望A.m1() - > B.m1(A),而不是A.m1() - > A.m1(B)

示例2:

由于4给出了"m1(A) in A",我在这里期待同样的事情,因为流程对我来说似乎是一样的。

仅看示例1,我期望A.m2() - > A.m2(A),而不是A.m2() - > B.m2(A)

示例3:

bb.m2();打印m2(A) in B

我希望m2(A) in A,因为它会被投放到A。为什么要拨打B.m2(A)

例4。

如果它转换为B.m3(),则会调用A。为什么?我希望它可以调用A.m3(),因为它已被投放

1 个答案:

答案 0 :(得分:1)

示例1 m1(new B());的调用位于课程A内。 A不知道子类的任何实现细节(例如B的细节),因此它只知道A.m1(A)
示例2 :您可以添加一个简单的System.out.println(this.getClass());来显示this的类。它会告诉您this的类型是$B。您已在B上调用该方法,并且B知道该方法m2(B b),以便调用一个方法。
示例3:与5相同的原因。 示例4:它被称为B.m3(),后者又调用super.m1(b);。这会调用超级方法A.m1(A a),因为B扩展了A。由于B.m1(B b)上的显式调用,它无法调用super。如果A中没有足够的方法,则会出现编译错误。

<强>更新

示例1 示例2 之间的差异:
示例1 b.m1();中调用了类m1()的方法A。因为在调用m1()的那一刻,编译器只知道类型是A而不是B。我们假设您只会看到A类型的变量,那么您只能看到A的方法。因此,m1(new B());的后续调用会导致调用A方法。编译器没有B可用于调用它的方法 在示例2 中,类型为b的变量B,因此编译器可以查看A的所有方法和B的所有方法。因此,编译器知道方法B.m2(B b)并可以在m2(this)的后续调用中调用它。