¿Cuál es el uso de ‘anulación abstracta’ en C #?

Solo por curiosidad intenté sobreescribir un método abstracto en la clase base, y el método de la implementación abstracta. Como a continuación:

public abstract class FirstAbstract { public abstract void SomeMethod(); } public abstract class SecondAbstract : FirstAbstract { public abstract override void SomeMethod(); //?? what sense does this make? no implementaion would anyway force the derived classes to implement abstract method? } 

Es curioso saber por qué el comstackdor de C # permite escribir “anulación abstracta”. ¿No es redundante? Debería haber un error de tiempo de comstackción para hacer algo como esto. ¿Sirve para algún caso de uso?

Gracias por tu interés.

Hay un ejemplo útil para esto en MSDN : básicamente, puede forzar una clase derivada para proporcionar una nueva implementación para un método.

 public class D { public virtual void DoWork(int i) { // Original implementation. } } public abstract class E : D { public abstract override void DoWork(int i); } public class F : E { public override void DoWork(int i) { // New implementation. } } 

Si un método virtual se declara abstracto, sigue siendo virtual para cualquier clase que herede de la clase abstracta. Una clase que hereda un método abstracto no puede acceder a la implementación original del método: en el ejemplo anterior, DoWork en la clase F no puede llamar a DoWork en la clase D. De esta forma, una clase abstracta puede forzar clases derivadas para proporcionar nuevas implementaciones de métodos para métodos virtuales .

Encuentro realmente útil para garantizar la ToString() correcta de ToString() en las clases derivadas. Supongamos que tiene una clase base abstracta y realmente desea que todas las clases derivadas definan la implementación de ToString() mala ToString() porque la está utilizando activamente. Puedes hacerlo muy elegantemente con abstract override :

 public abstract class Base { public abstract override string ToString(); } 

Es una señal clara para los implementadores que ToString() se utilizará en la clase base de alguna manera (como escribir salida al usuario). Normalmente, no pensarían en definir esta anulación.

Curiosamente, la versión de Roslyn del comstackdor de C # tiene un método de anulación abstracta, que me pareció bastante extraño para escribir un artículo sobre:

http://ericlippert.com/2011/02/07/strange-but-legal/

Imagine que SecondAbstract encuentra en el medio de una jerarquía de tres clases, y desea implementar algunos métodos abstractos desde su base FirstAbstract mientras deja algún otro método X implementado a partir de su ThirdAbstract secundario.

En este caso, SecondAbstract se ve obligado a decorar el método X con abstract ya que no desea proporcionar una implementación; al mismo tiempo, se ve obligado a decorarlo con override ya que no está definiendo un nuevo método X, pero quiere transferir la responsabilidad de implementar X a su hijo. Por lo tanto, abstract override .

En general, los conceptos modelados por abstract y override son ortogonales. Las primeras fuerzas derivaron clases para implementar un método, mientras que el segundo reconoce que un método es el mismo que el especificado en una clase base y no uno new .

Por lo tanto:

  • ninguna palabra clave: método “simple”
  • solo abstract : la clase derivada debe implementar
  • solo override : implementación del método definido en la clase base
  • abstract override : la clase derivada debe implementar un método definido en la clase base

Esto se hace porque en la clase infantil no se puede tener abstract método abstract con el mismo nombre que en la clase base. override le dice al comstackdor que está anulando el comportamiento de la clase base.

Espero que esto es lo que estás buscando.

Si no declara SomeMethod como abstract override en SecondAbstract , el comstackdor esperaría que esa clase contenga una implementación del método. Con abstract override , está claro que la implementación debe estar en una clase derivada de SecondAbstract y no en SecondAbstract .

Espero que esto ayude…

Este patrón de diseño se conoce como el patrón de Método de plantilla.

Página de Wikipedia sobre métodos de plantilla

Un ejemplo simple, no de software: hay un montón de unidades militares: tanques, jets, soldados, acorazados, etc. Todos deben implementar algunos métodos comunes, pero los implementarán de manera muy diferente:

  • Movimiento()
  • Ataque()
  • Retirada()
  • Descanso()

etc …