在我的抽象课中,我有类似的东西:
public Object methodIWantToExpose(){
// ...
methodIDontWantExposed()
// ...
}
protected abstract void methodIDontWantExposed();
问题是,我想强制扩展methodIDontWantExposed()的人使其受到保护,因为我不希望扩展类同时暴露methodIDontWantExposed和methodIWantToExpose。
有没有办法做到这一点(或者一种可能避免我的问题的不同方法)?
答案 0 :(得分:37)
没有。子类可以始终使方法更加公开。
即使他们不能用你班上的方法做到这一点,他们总是会写:
public void callsMethodIDontWantExposed() {
methodIDontWantExposed();
}
......所以你处于同样的境地。
答案 1 :(得分:34)
不,在重写方法时,子类总是可以扩大访问范围。没有办法阻止这种情况。但是,通常,当我覆盖方法时,我很少将可见性从受保护更改为公共。仔细记录方法的目的可能足以说服实施者在这种情况下这是一个坏主意。
如果您真的想以私有方式封装行为,可以按以下方式执行操作:
abstract class YourClass {
private HandlerInterface unexposedHandler;
YourClass(HandlerInterface handler) {
unexposedHandler = handler;
}
public Object methodIWantToExpose(){
// ...
handler.methodIDontWantExposed();
// ...
}
}
使用Java 8,您甚至可以使HandlerInterface
成为一个功能界面,并方便地使用lambda,如下所示:
class YourSubClass extends YourClass {
YourSubClass() {
super(() -> {
System.out.println("This is the unexposed code");
});
}
...
}
答案 2 :(得分:6)
这取决于您是否希望您的类的用户能够覆盖该方法。如果让它们覆盖它,它们总是可以使用公共方法覆盖它。
有些方法可以避免让他们覆盖该方法:
在抽象类中实现它并使其成为final,因此无法覆盖它。
使其成为私有包,并在属于同一个包的一个或多个子类中实现它。由于您是实现它的人,您可以将其保密,或将其更改为最终保护,以便您的包外的子类无法使用公共方法覆盖它。
< / LI> 醇>答案 3 :(得分:6)
在某些情况下,您可以完全避免使用抽象方法(实际上甚至是子类),而是可以使用枚举中定义的strategy。
当然,使用的枚举实例仍然可以暴露,但至少它保证允许的唯一行为是枚举中定义的行为。
所以你的解决方案是这样的:
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();
// ...
}
}
答案 4 :(得分:5)
您不能这样做,因为提高方法的可见性不会破坏基类合同。
查看Why Java allows increasing the visibility of protected methods in child class?
答案 5 :(得分:4)
不,你不能。如果它是一个具体的方法,你可以把它私有化。在你的情况下,没有聪明的方法来阻止扩展类声明它公开(你当然可以评论该方法,说它不应该公开)。