当有人重写抽象方法时,我能强制保护抽象方法吗?

在我的抽象类中,我有这样的东西:

public Object methodIWantToExpose(){ // ... methodIDontWantExposed() // ... } protected abstract void methodIDontWantExposed(); 

事情是,我想强制扩展methodIDontWantExposed()的人来保护它,因为我不希望扩展类同时暴露了methodIDontWantExposed和methodIWantToExpose。

有没有办法做到这一点(或不同的方法,可以避免我的问题)?

不,子类在覆盖方法时总是可以扩大访问范围。 没有办法阻止这一点。 但是,通常情况下,当我重写一个方法时,我很less将可见性从保护变为公共。 仔细logging方法的目的可能足以说服实施者,在这种情况下这将是一个坏主意。

如果你真的想要以一种私人的方式封装行为,你可以按照下面的方法做一些事情:

 abstract class YourClass { private HandlerInterface unexposedHandler; YourClass(HandlerInterface handler) { unexposedHandler = handler; } public Object methodIWantToExpose(){ // ... handler.methodIDontWantExposed(); // ... } } 

使用Java 8,你甚至可以使HandlerInterface成为一个函数接口,并且可以方便地使用lambdaexpression式,如下所示:

 class YourSubClass extends YourClass { YourSubClass() { super(() -> { System.out.println("This is the unexposed code"); }); } ... } 

不可以。一个子类总是可以使方法更公开。

即使他们不能用你class上的方法来做到这一点,他们总是可以这样写:

 public void callsMethodIDontWantExposed() { methodIDontWantExposed(); } 

…所以你会处于相同的情况。

这取决于您是否希望您的课程的用户能够覆盖该方法。 如果你让它们覆盖它,它们总是可以用一个公共方法覆盖它。

有些方法可以避免让它们重写该方法:

  1. 让它在抽象类中实现并使其成为最终的,所以它不能被覆盖。

  2. 将它打包为私有,并在属于同一个包的更多子类中的一个中实现它。 既然你是一个实现它的人,你可以保持私有包,或将其改为最终保护,以便包之外的子类不能用公有方法覆盖它。

在某些情况下,您可以避免抽象方法(甚至是子类化),而是可以使用在枚举中定义的策略 。

当然,所使用的枚举实例仍然可以被暴露,但是至less可以保证只允许在你的枚举中定义的行为。

所以你的解决scheme是这样的:

 enum Behaviour { ONE() { public Object doSomething() { return "ONE"; } }; public abstract Object doSomething(); } // and your class public abstract class MyClass { private final Behaviour behaviour; protected MyClass( Behaviour behaviour ) { this.behaviour = behaviour; } public final void methodIWantToExpose() { // ... behaviour.doSomething(); // ... } } 

你不能这样做,因为提高方法的可见性不会破坏基类合同。

看看为什么Java允许增加子类中受保护方法的可见性?

不,你不能。 如果这是一个具体的方法,你可以把它变成私人的。 在你的情况下,没有一个聪明的办法来阻止扩展类声明它是公开的(你当然可以评论该方法,说不应该公开)。