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

wpx232ag  于 2021-07-11  发布在  Java
关注(0)|答案(2)|浏览(271)

我在最近的一次采访中被问到这个问题。想找人帮忙。
类具有从构造函数触发的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文件(.jar)的一部分,那么我们如何确保在示例化类b时调用a.foo()而不是重写b.foo()?
条件:
假设jar是共享给其他用户的,我们不能破坏我的客户机代码,将方法标记为private/final。
从类b调用super.foo()也不是一个选项,因为我们不拥有类b,也不能限制用户。

de90aj5v

de90aj5v1#

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() 调用,不能重写。
这里更重要的一点是,您不应该从构造函数调用可重写的方法。

gab6jxml

gab6jxml2#

标记a的 foo 方法as final . 这是唯一的办法。
为了仍然允许b在初始化时也获得ping,解决方案是两个阶段的构造:a的构造函数调用最终的foo()方法,但是作为foo()方法的一部分,也会调用foo2或subfo,或者您想调用它的任何东西,并且该方法在a中定义为noop(不执行任何操作)。
通常这种final 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() {}
}

相关问题