He estado codificando durante aproximadamente 8 años, sin embargo, todavía encuentro que la herencia es demasiado flexible y, a veces, te confunde totalmente con el código que has escrito. Un ejemplo más simple sería:
abstract class AClass {
protected void method1() {
if(check()) {
do1();
} else {
do2();
}
}
protected abstract void do1();
protected abstract void do2();
}
La intención de la clase es que las personas puedan implementar do1 () y do2 () para que se pueda hacer alguna lógica adicional, sin embargo, a veces las personas deciden sobrecargar el método1 (), y luego las cosas se complican de inmediato.
Solo encuentro en el patrón de estrategia, el código se reutiliza bien a través de la herencia, en la mayoría de los casos, el diseñador de la clase base conoce muy bien sus subclases, y esa herencia es totalmente opcional.
Tengo una clase que es heredada por 4 clases: un IoHandler, y son subclases para el lado del servidor, el lado del cliente, el servidor perimetral, el servidor de origen, y comienza a volverme loco. Siempre estuve en la refactorización de códigos, siempre salí con ideas que creo que funcionarían y luego se demostró que no. Se dice que el cerebro humano solo puede contener 7 piezas de información una vez, ¿llevo demasiadas?
fuente
final
[si estás usando Java]. Esto efectivamente lo hace no virtual y no se puede sobrecargar. Perfecto para usar en esta circunstancia [patrón de plantilla]Respuestas:
Una vez que sigas repitiendo estos patrones, ya no parecen tan complicados.
Además, debe conocer las clases base antes de heredarlas. Y la herencia no será opcional mientras se reutilice el código común. Tome cualquier otro patrón como fábrica abstracta / compuesto: esa herencia en realidad tiene un propósito.
Regla general: no use la herencia solo para mantener un montón de clases juntas. Úselo donde tenga sentido. En el ejemplo artificial, el usuario de la clase secundaria que está sobrecargando el método1 debe tener alguna razón seria para hacerlo. (OTOH, también he querido una forma de evitar la sobrecarga de ciertas funciones solo, para evitar esto). Y antes de usar esa clase infantil, también debe conocer esta peculiaridad. Pero un patrón de estrategia pura no lo hará; si lo hace, hágala muy bien.
Si da su ejemplo de código real, puede haber personas aquí que puedan revisarlo por usted.
fuente
Sí, puede ser muy complicado ... y estás en buena compañía.
Joshua Bloch en Java efectivo captura muy bien algunos de los problemas de herencia y recomienda favorecer la composición en lugar de la herencia.
fuente
Creo que tu pregunta es demasiado vaga y general. Lo que describe parece un problema complejo, con o sin herencia. Entonces, en mi humilde opinión, es completamente normal que estés luchando con eso.
Por supuesto, en algunos casos, la herencia no es la mejor herramienta para un trabajo (referencia obligatoria a "favorecer la composición sobre la herencia" ;-). Pero cuando se usa con cuidado, me resulta útil. Según su descripción, es difícil decidir si la herencia es o no la herramienta adecuada para su caso.
fuente
si sus métodos son demasiado complejos, hace que las subclases lloren
haz que tus métodos hagan una cosa específica
fuente
La herencia de composición reduce el vector de cambio.
Imagine que su solución está implementada y utiliza AClass en 300 lugares diferentes de la base del código, y ahora es necesario cambiar 45 de las llamadas al método1 () para que se llame al método do3 () en lugar de do2 ().
Puede implementar do3 () en la interfaz IAnInterface (es de esperar que todas las implementaciones de la interfaz puedan manejar un método do3 () fácilmente) y crear un BClass que llame a do1 () o do3 () en la llamada method1 () y cambie las 45 referencias a tanto la clase AC como la dependencia inyectada.
ahora imagen que implementa este mismo cambio para do4 (), do5 (), ...
O podrías hacer lo siguiente ...
Ahora solo necesita implementar una segunda fábrica que devuelva Doer1 o Doer2 y cambiar la inyección de fábrica en 45 lugares. AClass no cambia, IAnInterface no cambia y puede manejar fácilmente más cambios como do4 (), do5 ().
fuente
Por qué no hacer:
(Creo que el final es el equivalente de "sellado" en C #, alguien corríjame si esa sintaxis es incorrecta).
La inyección de dependencia / IoC significa que puede heredar solo los métodos que realmente desea que las personas puedan cambiar, lo que creo que resuelve su problema. Además, no parece que la clase principal realmente haga lo que sea do1 y do2, más que delega las llamadas en sus subclases en función de una condición: ¡está rompiendo la separación de las preocupaciones!
fuente