繁体   English   中英

Java继承:创建子类实例时如何调用超类方法?

[英]Java Inheritance: How to invoke super class method when subclass instance is created?

我在最近的一次采访中被问到这个问题。 寻求帮助。

  • A 类具有从构造函数触发的 foo() 方法。
public class A {

    public A() {
        foo();
    }

    public void foo() {
        System.out.println("In foo method in class A");
    }
}

B 类覆盖 A 类中的 foo 方法。

public class B extends A {

    @Override
    public void foo() {
        System.out.println("In foo method in class B");
    }
}

现在,如果我们创建类 B 的实例,B 中的 foo() 方法将被调用。

A a = new B();
prints: "In foo method in class B"

问题:假设我们拥有类 A,它是 jar 文件 (abc.jar) 的一部分,我们如何确保类 B 何时被实例化 A.foo() 被调用而不是覆盖 B.foo()?

状况:

  1. 想象一下,jar 被共享给其他用户,我们不能破坏客户端代码,因为我将方法标记为 private/final。

  2. 同样从 B 类调用 super.foo() 也不是一个选项,因为我们不拥有 B 类并且不能限制用户。

public class A {

    public A() {
        fooInternal();
    }

    public void foo() {
        fooInternal();
    }

    private final void fooInternal() {
        System.out.println("In foo method in class A");
    }
}

您不能让它调用A.foo() ,因为该方法已被覆盖。 你只能让它调用A.foo()调用的方法,并且不能被覆盖。

这里更重要的一点是你永远不应该从构造函数调用可覆盖的方法。

将 A 的foo方法标记为final 这是唯一的方法。

为了仍然允许 B 在初始化时也获得 ping,解决方案是一个两阶段的构造:A 的构造函数调用最终的 foo() 方法,但作为 foo() 方法的一部分,foo2 或 subfoo 或其他任何方法你想调用它,也被调用,并且该方法在 A 中定义为一个 noop(什么都不做)。

通常这样的最终 init() 样式的方法也应该是私有的。 基于共同的逻辑:“init”操作也是一个概念,外部代码可能希望在某个任意的稍后时间点第二次调用的可能性有多大? 不可能,这就是为什么它应该是私有的。 一旦你这样做了,那么私有方法本质上就是最终的,所以它会解决这个问题:

class A {
    public A() {
        init0();
    }

    private final init0() {
        // do stuff here - subclasses won't stop you.
        init();
    }

    // B can override this if it wants.
    protected void init() {}
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM