Java 中的四级继承

Four level Inheritance in Java

我一直在努力理解 java 的一些使用继承来计算输出的代码。代码如下:

class A
{
    public int calc(double num) {
        System.out.println("calc de A");
        return (int)(num+1);

    }
}

class B extends A
{
    public int calc(long num) {
        System.out.println("calc de B");
        return (int)(num+2);

    }
}

class C extends B
{
    public int calc(int num) {
        System.out.println("calc de C");
        return num+3;

    }
}

class D extends C
{
    public int calc(float num) {
        System.out.println("calc de D");
        return (int)(num+4);

    }
}

class Main
{
    public static void main(String[] args)
    {
        int num1 = 10;
        long num2 = num1;

        A a1 = new D();
        A a2 = new D();

        int result = a1.calc(num1) + a2.calc(num2);

        System.out.println("Numero: "+ result);
    }
}

我和我的朋友们认为控制台的输出应该是:

calc de C
calc de B
Numero: 25

但是我们运行在Eclipse和Ideone(link:http://ideone.com/CTdklv)中测试了一下,给出的答案是

calc de A
calc de A
Numero: 22

如果方法的签名不同,谁能解释为什么输出是 22。

我们认为,如果您使用 int 作为参数调用 calc 方法,您应该转到 B class 的 calc 方法,而不是 A class.

感谢您的帮助! 谢谢。

在Java中,可以调用哪些重载是由引用变量的类型决定的(15.12.1):

If the form (of the method invocation expression) is ExpressionName . [TypeArguments] Identifier, then the class or interface to search is the declared type T of the variable denoted by ExpressionName if T is a class or interface type, or the upper bound of T if T is a type variable.

因为 a1a2 被声明为 A,你可以给它们分配一个 D 但你只能从 [=15= 调用方法].

如果稍微更改一下类型,您会发现它是这样工作的:

class A {
    void m(int i) {}
}

class B extends A {
    void m(double d) {}
}

A a = new B();

double d = 0d;
a.m(d); // won't compile
        // will say something like
        // 'double can not be converted to int'

因此,如果您将 a1a2 更改为 D

D a1 = new D();
D a2 = new D();

输出应该如您所料,因为 BCD 中的重载可供调用。


请注意,它也适用于覆盖。

class A {
    protected void m() {}
}

class B extends A {
    @Override
    public void m() {}
}

// in another package...
B b = new B();
b.m(); // call m because it is public in B
A a = b;
a.m(); // won't compile because it is protected in A

哪些方法可用取决于引用的类型。