java - poo - para que sirve una clase abstracta
¿Puedo forzar que los métodos abstractos estén protegidos cuando alguien los anula? (6)
En mi clase abstracta, tengo algo como esto:
public Object methodIWantToExpose(){
// ...
methodIDontWantExposed()
// ...
}
protected abstract void methodIDontWantExposed();
La cuestión es que quiero forzar a la persona que extiende el métodoIDontWantExposed () para que lo proteja, porque no quiero que la clase extendida tenga tanto methodIDontWantExposed como methodIWantToExpose expuestos.
¿Hay alguna manera de hacer esto (o un enfoque diferente que podría evitar mi problema)?
Depende de si desea que los usuarios de su clase puedan anular ese método o no. Si les permite anularlo, siempre pueden anularlo con un método público.
Algunas formas en que puede evitar dejar que anulen ese método:
Haga que se implemente en la clase abstracta y hágalo definitivo, para que no pueda anularse.
Haga que el paquete sea privado e impleméntelo en una o más subclases que pertenezcan al mismo paquete. Como usted sería el que lo implementaría, puede mantenerlo privado o cambiarlo a protección final, de modo que las subclases fuera de su paquete no puedan sobrescribirlo con un método público.
En ciertos casos, puede evitar tener un método abstracto (e incluso subclases) por completo y, en su lugar, puede usar una strategy definida en una enumeración.
Por supuesto, la instancia enum utilizada aún puede estar expuesta, pero al menos está garantizado que los únicos comportamientos permitidos son los definidos en su enumeración.
Entonces su solución sería algo como esto:
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();
// ...
}
}
No se puede porque aumentar la visibilidad de un método no rompe el contrato de la clase base.
Eche un vistazo a ¿Por qué Java permite aumentar la visibilidad de los métodos protegidos en la clase infantil?
No, no puedes. Si fuera un método concreto, podrías hacerlo privado. En su caso, no hay una manera inteligente de evitar que una clase que se extiende lo declare público (por supuesto, puede comentar el método, diciendo que no debe hacerse público).
No, una subclase siempre puede ampliar el acceso al anular un método. No hay forma de prevenir eso. Por lo general, sin embargo, cuando anulo un método rara vez cambio la visibilidad de protegida a pública. Documentar cuidadosamente el propósito del método podría ser suficiente para convencer al implementador de que sería una mala idea en este caso.
Si realmente desea encapsular el comportamiento de manera privada, puede hacer algo en las siguientes líneas:
abstract class YourClass {
private HandlerInterface unexposedHandler;
YourClass(HandlerInterface handler) {
unexposedHandler = handler;
}
public Object methodIWantToExpose(){
// ...
handler.methodIDontWantExposed();
// ...
}
}
Con Java 8, podría incluso hacer de HandlerInterface
una interfaz funcional y usar convenientemente un lambda de la siguiente manera:
class YourSubClass extends YourClass {
YourSubClass() {
super(() -> {
System.out.println("This is the unexposed code");
});
}
...
}
No. Una subclase siempre puede hacer que un método sea más público.
Incluso si no pudieran hacer esto con el método que tienes en tu clase, siempre podrían escribir:
public void callsMethodIDontWantExposed() {
methodIDontWantExposed();
}
... así estarías en la misma situación.