Recientemente tuve que actualizar una clase base abstracta en algunos OSS que estaba usando para que fuera más verificable al hacerlos virtuales (no podía usar una interfaz ya que combinaba dos). Esto me hizo pensar si debería marcar todos los métodos que necesitaba virtuales, o si debería marcar todos los métodos / propiedades públicas virtuales. En general, estoy de acuerdo con Roy Osherove en que cada método debe hacerse virtual, pero me encontré con este artículo que me hizo pensar si esto era necesario o no . Sin embargo, voy a limitar esto a clases abstractas por simplicidad (si todos los métodos públicos concretos deberían ser virtuales es especialmente discutible, estoy seguro).
Pude ver dónde podría permitir que una subclase use un método, pero no querer anular la implementación. Sin embargo, siempre y cuando confíes en que se seguirá el Principio de sustitución de Liskov , ¿por qué no permitirías que se anule? Al marcarlo como abstracto, de todos modos está forzando un cierto aumento al presupuesto, por lo que me parece que todos los métodos públicos dentro de una clase abstracta deberían marcarse como virtuales.
Sin embargo, quería preguntar en caso de que hubiera algo en lo que no estaría pensando. ¿Deberían todos los métodos públicos dentro de una clase abstracta hacerse virtuales?
fuente
Respuestas:
Por ejemplo, porque quiero que la implementación del esqueleto de un algoritmo sea reparada, y solo permita que partes específicas sean (re) definidas por subclases. Esto es ampliamente conocido como el patrón del Método de la plantilla (énfasis a continuación por mí):
Actualizar
Algunos ejemplos concretos de proyectos en los que he estado trabajando:
En los primeros dos casos, la implementación heredada original usó la Estrategia , lo que resultó en una gran cantidad de código duplicado, que por supuesto a lo largo de los años creció diferencias sutiles aquí y allá, contenía muchos errores duplicados o ligeramente diferentes, y fue muy difícil de mantener. Refactorizar al método de plantilla (y algunas otras mejoras, como el uso de anotaciones Java) redujo el tamaño del código en aproximadamente un 40-70%.
Estos son solo los ejemplos más recientes que me vienen a la mente. Podría citar más casos de casi todos los proyectos en los que he estado trabajando hasta ahora.
fuente
Es perfectamente razonable, y a veces deseable tener métodos no virtuales en una clase base abstracta; el hecho de que sea una clase abstracta no significa necesariamente que cada parte de la misma deba ser utilizable polimórficamente.
Por ejemplo, es posible que desee utilizar el idioma 'Polimorfismo no virtual', por el cual una función se llama polimórficamente desde una función miembro no virtual, para garantizar que se cumplan ciertas condiciones previas o posteriores antes de que se llame a la función virtual
fuente
Es suficiente para que una clase contenga UN método virtual, para que la clase se vuelva abstracta. Es posible que desee prestar atención a los métodos que desea virtuales y cuáles no, de acuerdo con el tipo de polimorfismo que planea usar.
fuente
Pregúntese cuál es el uso de un método no virtual en una clase abstracta. Tal método debería tener una implementación para que sea útil. Pero si la clase tiene una implementación, ¿se puede llamar una clase abstracta? Incluso si el lenguaje / compilador lo permite, ¿tiene sentido? Personalmente, no lo creo. Tendría una clase normal con métodos abstractos que se espera que los descendientes implementen.
Mi idioma principal es Delphi, no C #. En Delphi, si marca un resumen de método, también debe marcarlo virtual o el compilador se queja. No he seguido los últimos cambios de idioma demasiado de cerca, pero si las clases abstractas están en o vendrían a Delphi, esperaría que el compilador se quejara de cualquier método no virtual, cualquier método privado y cualquier implementación de métodos para un resumen marcado de clase a nivel de clase.
fuente
abstract
, también debe marcar toda la claseabstract
.No hace que ciertos métodos sean virtuales porque no cree que sea así. Además, al hacer que ciertos métodos no sean virtuales, está indicando a los herederos qué métodos deben implementarse.
Personalmente, a menudo haré sobrecargas de métodos que existen por conveniencia, no virtuales, para que los usuarios de la clase puedan tener valores predeterminados consistentes y los implementadores ni siquiera puedan cometer el error de romper ese comportamiento implícito.
fuente