2012-01-18 13 views
41

Solo por curiosidad intenté sobreescribir un método abstracto en la clase base, y el método de la implementación abstracta. Como continuación:¿Cuál es el uso de "anulación abstracta" en C#?

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? 
} 

la curiosidad de saber qué compilador de C# permite escribir 'anulación abstracta'. ¿No es redundante? Debería haber un error de tiempo de compilación para hacer algo como esto. ¿Sirve para algún caso de uso?

Gracias por su interés.

+0

He usado esta función un par de veces. Definitivamente hay casos de uso. – ChaosPandion

+0

esto debería ayudar: http://blogs.msdn.com/b/jmstall/archive/2005/08/07/abstract-override.aspx – VS1

+0

¿por qué debería algo que es simplemente redundante causar un error de tiempo de compilación? – saus

Respuesta

54

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 abstracta, todavía es virtual a cualquier clase que hereda de la clase abstracta. Una clase que hereda un método abstracto no puede acceder a la implementación original de la método -en el ejemplo anterior, DoWork en clase F no puede llamar DoWork en clase D. De esta manera, una clase abstracta puede obligar a las clases derivadas a proporcionar nuevas implementaciones de métodos para los métodos virtuales.

+1

¿Qué sucede si hago algo como 'F ff = new F(); D dd = ff como D; dd.DoWork (0); '? ¿No llamaría eso la implementación de 'D'? Y si eso es cierto, ¿podría poner en el código 'DoWork (int i)' de 'F' algo así como' D dd = this como D; dd.DoWork (i); '? ¿Llamaría eso a la implementación de 'D'? – Blueriver

+0

@Blueriver como con cualquier miembro virtual, llamaría a la implementación del objeto real, por lo que en ese caso llamaría a la implementación de 'F'. –

0

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

Espero que esto es lo que estás buscando.

6

Imagínese que SecondAbstract está en el medio de una jerarquía de tres clases, y se quiere implementar algunos métodos abstractos de su base FirstAbstract, dejando algún otro método X a implementarse a partir de su niño ThirdAbstract.

En este caso, SecondAbstract está 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 la segunda reconoce que un método es el mismo que el especificado en una clase base y no un new.

Por lo tanto:

  • ni palabra clave: método "simple"
  • abstract solamente: clase derivada debe aplicar
  • override única: aplicación de método definido en la clase base
  • abstract override: clase derivada debe implementar un método definido en la clase base
+1

Pero no es necesario que SecondAbstract incluya el método X en absoluto, ya que SecondAbstract es una clase abstracta. Agregar X y decorarlo como anulación abstracta es equivalente a no incluir X en absoluto, que es lo que el OP significa redundante, supongo. – saus

+0

¿Significa que 'SecondAbstract' no está satisfecho con la implementación del método X de la clase base? – Eranga

0

Si no declaró SomeMethod como abstract override en SecondAbstract, el compilador 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 el propio SecondAbstract.

Espero que esto ayude ...

40

Encuentro realmente útil para asegurar la implementación 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 ToString() defectuosa porque la está utilizando activamente. Usted puede hacer que sea muy elegante con abstract override:

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

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

+0

Upvoted. Este es un gran ejemplo que realmente pertenece a este hilo. El mismo ejemplo también se dio en [una respuesta anterior en otro lugar] (http://stackoverflow.com/a/1769064/1336654) en Stack Overflow, solo para comparar. –

0

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

Wikipedia page on Template Methods

Un simple, ejemplo no software: Hay un montón de unidades militares: tanques, aviones, soldados, buques de guerra, etc. Todos ellos necesitan para poner en práctica algunos métodos comunes pero van a poner en práctica de manera muy diferente :

  • Mover()
  • Ataque()
  • Retiro()
  • Resto()

etc ...

Cuestiones relacionadas