重写方法是否可以具有与基类中的访问说明符不同的访问说明符?

2022-09-02 03:22:08

在抽象类中,我必须将哪个访问修饰符用于方法,以便子类可以决定它是否应为公共?是否有可能在Java中“覆盖”修饰符?

public abstract class A {

    ??? void method();
}

public class B extends A {
    @Override
    public void method(){
        // TODO
    }
}

public class C extends B {
    @Override
    private void method(){
        // TODO
    }
}

我知道如果有人调用,静态绑定会出现问题:

// Will work
A foo = new B()
foo.method();

// Compiler ?
A foo = new C();
foo.method();

但也许还有另一种方法。我怎样才能做到这一点?


答案 1

可以放宽限制,但不能使其更具限制性:

public abstract class A {
    protected void method();
}

public class B extends A {
    @Override
    public void method(){    // OK
    }
}

public class C extends A {
    @Override
    private void method(){    // not allowed
    }
}

制作原始方法也不起作用,因为此类方法在子类中不可见,因此无法覆盖。private

我建议使用s来选择性地公开或隐藏方法:interface

public interface WithMethod {
    // other methods
    void method();
}

public interface WithoutMethod {
    // other methods
    // no 'method()'
}

public abstract class A {
    protected void method();
}

public class B extends A implements WithMethod {
    @Override
    public void method(){
      //TODO
    }
}

public class C extends B implements WithoutMethod {
    // no 'method()'
}

...然后仅通过接口处理实例。


答案 2

重写方法时,只能将修饰符更改为更宽的修饰符,反之亦然。例如,此代码将有效:

public abstract class A {

    protected void method();
}

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

但是,如果您尝试缩小可见性范围,则会收到编译时错误:

public abstract class A {
    protected void method();
}

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

对于您的情况,我建议不要实现 ,因为 的抽象意味着存在一个非私有的:CAAmethod()

public class C {
    private void method(){
      //TODO
    }
}

另一种选择是在抛出运行时异常时进行实现:method()C

public class C extends A {

    @Override
    public void method(){
        throw new UnsupportedOperationException("C doesn't support callbacks to method()");
    }
}

推荐