似乎无法理解复杂的多态性

Ron*_*tor 16 java polymorphism

我正在研究CS,我们对多态性有疑问,但我无法解读.这是一个例子:

public class AA{
    public AA(){
        foo();
    }
    private void foo() {
        System.out.print("AA::foo ");
        goo();
    }
    public void goo(){
        System.out.print("AA::goo ");
    }
}

public class BB extends AA{
    public BB(){
        foo();
    }
    public void foo(){
        System.out.print("BB:foo ");
    }
    public void goo(){
        System.out.print("BB::goo ");
    }
    public static void main(String[] args){
        // Code goes here
    }
}
Run Code Online (Sandbox Code Playgroud)

在void main中我添加以下行:

AA a = new BB();
Run Code Online (Sandbox Code Playgroud)

首先是AA构造函数打印AA:foo然后goo()将它发送到BB的goo,为什么呢?

简单的多态性,如"动物 - >猫/蜘蛛/狗"很容易理解,但是当谈到这一点时,我只是迷失了.你能给我一些如何阅读这段代码的提示吗?有什么规则?

编辑:没有@Override注释,因为这是考试中的问题.

And*_*lko 15

说明

public class AA {

    private void foo() { ... }
    ^^^^^^^

}
Run Code Online (Sandbox Code Playgroud)

多态性不适用于private方法.子类不继承private方法,因此无法覆盖它们:

C从其直接超类继承超类的所有具体方法m(静态和实例),以下所有方法都为真:

  • m是直接超类的成员C.
  • mpublic,protected或者在与包相同的包中声明包访问权限C.
  • 没有在声明的方法C有签名是子签名的签名m.

Java语言规范 - 8.4.8.继承,压倒和隐藏

因此,foo()来自A构造函数的调用不会调用BB#foo,而是调用AA#foo.

goo()内部调用AA#foo是指被覆盖的方法BB#goo.这里,使用public方法,方法覆盖和多态.


这有点棘手,所以我建议你把@Override注释放在它应该是的任何地方.

public class BB extends AA {

    @Override   // it doesn't compile - no overriding here
    public void foo() { ... }
    @Override   // it does override
    public void goo() { ... }

}
Run Code Online (Sandbox Code Playgroud)

检测另一个问题可能也有帮助:

当程序员意图覆盖它时会偶尔重载方法声明,从而导致细微的问题.注释类型支持早期检测此类问题.Override

如果类型中的方法声明T使用注释@Override,但该方法没有覆盖T超类型中声明的方法T,或者不是覆盖等效于公共方法Object,则会发生编译时错误.

Java语言规范 - 9.6.4.4. @Override

插图

如果构造函数体不是以显式构造函数调用开始并且声明的构造函数不是原始类的一部分Object,那么构造函数体隐式地以超类构造函数调用开始super();,调用其直接超类的构造函数,不带参数.

Java语言规范 - 8.8.7.构造体

简而言之,

public BB() {
    foo();
}
Run Code Online (Sandbox Code Playgroud)

变成

public BB() {
    super();
    foo();
}
Run Code Online (Sandbox Code Playgroud)

super();记住,我们可以进行下一个说明:

new BB()
        AA()                       // super(); -> AA constructor
                A#foo()            // private method call 
                        B#goo()    // polymorphic method call
        BB()                       // BB constructor
                B#foo()            // plain method call 
Run Code Online (Sandbox Code Playgroud)