2011-08-12 16 views
9

Si tengo un proyecto que contiene clases similares y algunos pueden utilizar la misma aplicación, pero en la mayoría de los casos la aplicación de su propia manera de manejar los métodos definidos en una interfaz o clase abstracta. Estoy tratando de averiguar si una clase de interfaz/resumen es mejor o no. No entiendo el sentido de una interfaz si puedes usar una clase abstracta con métodos abstractos virtuales.¿Es la misma cosa una interfaz y una clase abstracta con solo métodos abstractos virtuales?

Aquí es una interfaz:

public interface IAthlete 
{ 
    void Run(); 
} 

Aquí es una clase abstracta:

public abstract class Athlete 
{ 
    public abstract void Run(); 
} 

Aquí es una implementación de la interfaz:

public class Sprinter : IAthlete 
{ 
    public void Run() 
    { 
     Console.WriteLine("Running Fast...."); 
    } 
} 

Aquí es una extensión de la clase abstracta:

public class MarathonRunner : Athlete 
{ 
    public override void Run() 
    { 
     Console.Write("Jogging...."); 
    } 
} 

Ahora, si decido agregar un método llamado Stop a la interfaz o al método abstracto, Sprinter y MarathonRunner se rompen y dado que puedo proporcionar alguna implementación predeterminada para abstraer, parece una mejor opción. ¿Me estoy perdiendo de algo?

+3

Supongo que estamos hablando de Java aquí. La principal diferencia es que en Java, una clase puede implementar varias interfaces, pero solo puede extender una superclase. Las interfaces son, por lo tanto, un poco más flexibles. –

+0

lo siento C#, actualizaré la etiqueta. – Xaisoft

+0

http://stackoverflow.com/questions/2308786/abstract-classes-and-interfaces-in-c/2308801#2308801 –

Respuesta

6

Hay 2 principales diferencias entre las interfaces abstractas y superclases:

Las clases abstractas

  • la reutilización de código es posible mediante el uso de una super-clase abstracta
  • sólo se puede heredar una super- clase

Interfaces

  • cada método tiene que ser implementado en cada subclase
  • una clase puede heredar más de 1 interfaz (herencia múltiple)
+0

Si declara una clase abstracta con todos los métodos abstractos, ¿no la clase que se extiende la clase abstracta tiene que implementar todos los métodos como una interfaz, así que esto es lo que me confunde. – Xaisoft

+1

+1 - Aunque, técnicamente, puede agregar 'implementaciones' a las interfaces con métodos de extensión. = D – Tejs

+2

@Xaisoft - Sí, la clase derivada necesitaría anular todos los métodos abstractos. Considere una clase abstracta como un superconjunto de funcionalidad de interfaz sin la capacidad de usar herencia múltiple. – Tejs

-1

Interfaces son una manera btter ir como el consenso actual entre el .NET comunidad de desarrolladores es que se debe favorecer la composición sobre la herencia, por lo que las interfaces son una estrategia mucho mejor (pensar en recipientes para inyección y cómo muy útil que también lo son, y no nos empezar a trabajar en la unidad de pruebas). también, las clases pueden implementar muchas interfaces pero solo pueden heredar de una clase (abstracta o de otro tipo). también las estructuras pueden implementar interfaces pero no heredar de otra clase. A nivel de ejecución, las interfaces son más eficientes que el tiempo de ejecución no tiene que caminar por la pila de herencia con el fin de averiguar las implicaciones polimórficas de llamar a un miembro específico.

+0

Tu respuesta es difícil – Atreys

1

En el caso en que todo lo que tiene es un pieza común para extraer, tiene toda la razón de que no hay una diferencia sustancial entre los dos. Pero esto es más bien como decir "en el caso de agregar 1 a 2, no hay diferencia entre int y double" - es técnicamente cierto, pero no es una guía particularmente útil para saber cómo pensar.

En caso de que haya más complejidad que esto (es decir, en la mayoría de los casos) habrá más clases y elementos de comportamiento común para extraer. Entonces usted tiene que empezar a hacer una significativa elección entre la herencia de clases y la implementación de la interfaz, teniendo en cuenta factores como:

  • sólo tienes una oportunidad de elegir una clase base, pero se puede aplicar tantas interfaces como se como
  • si desea que su 'padre' que hacer ningún trabajo, que no es necesario que haya una clase de una interfaz

y así sucesivamente.

En general, los semántica de sus clases que deben guiar - donde las 'cosas' tienen una "una" relación (como MarathonRunner de atleta), se sugiere herencia; donde las "cosas" tienen un "PUEDO CUMPLIR EL CONTRATO DE A" (como, por ejemplo, Persona a corredor), se sugiere la implementación de la interfaz.

0

Interfaces son una característica muy útil, y son muy similares a clases abstractas, y en algunas circunstancias, intercambiables con clases abstractas.

Pero, no salte directamente a interfaces, quite la cantidad que tiene que (antipattern muy común en los desarrolladores de Java). Sugiero, leyendo tu ejemplo, que te apegues a las clases abstractas.

La mayoría de las veces solo uso interfaces, cuando tengo varias clases no relacionadas, y las necesito para tener miembros comunes, como si estas clases provinieran de la misma clase base.

En su ejemplo, está tratando de encontrar lo que sucede si necesita un nuevo método stop al agregar un método virtual base. Estos se pueden resolver con un enfoque diferente, que no es Clases abstractas versus interfaces.

Hay 3 opciones:

(1) Añadir un método abstracto que obligar al programador anularlo, con el fin de crear instancias de objetos.

(2) Agregue un nuevo método virtual que hace algo, pero no tiene que ser anulado.

(3) Agregue un nuevo método que no haga nada, tal vez se aplique a su caso.

// cannot instantiate an abstract class 
public abstract class Athlete 
{ 
    // helper method: 
    public /* non-abstract */ void DoNothing() 
    { 
     // does nothing on purpouse !!! 
    } 

    // (1) virtual & abstract method, must be overriden 
    public abstract void Run(); 


    // (2) new virtual method, doesn't need to be overriden, 
    // but, maybe you dont like what it does 
    public virtual void Stop() 
    { 
     Message.Show("Stop !!!"); 
    } 

    // (3) new virtual method, doesn't need to be overriden, 
    // its safe to be called 
    public virtual void TakeBreak() 
    { 
     // works like an abstract virtual method, but, you don't need to override 
     DoNothing(); 
    } 
} // class Athlete 

// in a non abstract class, you must override all abstract methods 
public /* non-abstract */ class Runner: Athlete 
{ 
    public override void Run() 
    { 
     DoNothing(); 
    } 

    public override void Stop() 
    { 
     DoNothing(); 
    } 

    // don't need to override this method 
    // public virtual void TakeBreak(); 

} // class Trekker 

// ... 

Runner ARunner = new Runner(); 
ARunner.Run(); 
ARunner.Stop(); 
ARunner.TakeBreak(); 

El tercer tipo de método virtual, que puede aplicarse a su ejemplo, no logra' tienen un nombre especial, ya enviar una pregunta sobre ello en stackoverflow, pero, nadie sabía un nombre especial para este caso.

Saludos.

0

Una diferencia importante entre las interfaces y las clases abstractas es cómo manejan sus miembros la herencia multigeneracional.Supongamos que hay una clase abstracta BaseFoo con el método abstracto Bar y la interfaz IFoo con el método Boz; clase Foo hereda BaseFoo e implementa IFoo, y la clase DerivedFoo hereda de Foo.

Si DerivedFoo necesita para anular BaseFoo.Bar, puede hacerlo, y su anulación puede llamar base.Bar() si se tiene que utilizar la aplicación de su matriz. Si Foo implementos Boz implícitamente el uso de un método virtual, entonces DerivedFoo puede anular ese método y llamar base.Boz() (la anulación de ser una función de la clase en lugar de la interfaz) pero si Foo implementa explícitamente IFoo.Boz, entonces la única manera para que DerivedFoo para cambiar el comportamiento de IFoo.Boz será para volver a implementarlo. Si lo hace, entonces la implementación de Foo de IFoo.Boz se volverá inaccesible, incluso dentro de la implementación de DerivedFoo del mismo miembro de interfaz.

Cuestiones relacionadas