jus*_*ame 36 java access-modifiers
在我的抽象课中,我有这样的事情:
public Object methodIWantToExpose(){
// ...
methodIDontWantExposed()
// ...
}
protected abstract void methodIDontWantExposed();
Run Code Online (Sandbox Code Playgroud)
问题是,我想强制扩展methodIDontWantExposed()的人使其受到保护,因为我不希望扩展类同时暴露methodIDontWantExposed和methodIWantToExpose.
有没有办法做到这一点(或一种可能避免我的问题的不同方法)?
Jon*_*eet 37
不可以.子类总是可以使方法更公开.
即使他们不能用你班上的方法做到这一点,他们也可以写:
public void callsMethodIDontWantExposed() {
methodIDontWantExposed();
}
Run Code Online (Sandbox Code Playgroud)
......所以你会遇到同样的情况.
aio*_*obe 34
不,在重写方法时,子类总是可以扩大访问范围.没有办法阻止这一点.但是,通常,当我覆盖方法时,我很少将可见性从受保护更改为公共.仔细记录方法的目的可能足以说服实施者在这种情况下这是一个坏主意.
如果您真的想以私有方式封装行为,可以按以下方式执行操作:
abstract class YourClass {
private HandlerInterface unexposedHandler;
YourClass(HandlerInterface handler) {
unexposedHandler = handler;
}
public Object methodIWantToExpose(){
// ...
handler.methodIDontWantExposed();
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
使用Java 8,您甚至可以创建HandlerInterface一个功能界面并方便地使用lambda,如下所示:
class YourSubClass extends YourClass {
YourSubClass() {
super(() -> {
System.out.println("This is the unexposed code");
});
}
...
}
Run Code Online (Sandbox Code Playgroud)
这取决于您是否希望您的类的用户能够覆盖该方法.如果让它们覆盖它,它们总是可以使用公共方法覆盖它.
有些方法可以避免让它们覆盖该方法:
它是在抽象类中实现并使其成为final,因此无法覆盖它.
使其包为私有,并在属于同一个包的一个或多个子类中实现它.由于您是实现它的人,您可以将其保密,或将其更改为最终保护,以便您的包外的子类无法使用公共方法覆盖它.
在某些情况下,您可以完全避免使用抽象方法(实际上甚至是子类),而是可以使用枚举中定义的策略.
当然,使用的枚举实例仍然可以暴露,但至少可以保证允许的唯一行为是枚举中定义的行为.
所以你的解决方案是这样的:
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();
// ...
}
}
Run Code Online (Sandbox Code Playgroud)