2008-11-01 8 views
7

Hoy alguien me dijo que la implementación de la interfaz en C# es simplemente una relación "Can-Do", no una relación "Is-A". Esto entra en conflicto con mi creencia desde hace mucho tiempo en LSP (Principio de sustitución de Liskov). Siempre pienso que toda herencia debe significar una relación "Is-A".La relación de implementación de la interfaz C# es solo una relación de "se puede hacer".

Por lo tanto, si la implementación de la interfaz es solo una relación de "se puede hacer". ¿Qué pasa si hay una interfaz "IHuman" y "IEngineer", y una clase "Programmer" hereda de "IHuman" & "IEngineer"? Sin duda, un "Programador" es un "IHuman" y un "IEngineer".

Si solo se trata de una relación "Can-Do", ¿significa que no podemos esperar que el comportamiento de la instancia del "Programador" sea diferente cuando se trata como IHuman y se trata como IEngineer?

Respuesta

14

En mi experiencia, realmente no ayuda mucho pensar en las relaciones "es-a" y "puedo hacerlo". Te metes rápidamente en problemas. Es un desajuste de impedancia entre el mundo real y OO, básicamente. Por mucho que la gente realmente hable sobre modelar el mundo real, es fundamental que comprenda qué significan las relaciones entre los tipos en la plataforma que está utilizando.

Algunas veces, las interfaces se pueden usar como capacidades, y algunas veces pueden representar una relación normal "is-a". No me preocuparía demasiado por eso, solo asegúrate de que entiendes lo que pueden hacer y lo que no.

+0

La lectura de su libro de Jon. Es muy bueno. –

+0

@Iain: Me alegra que lo estés disfrutando. Envíame tus comentarios cuando hayas terminado :) –

+0

¿Qué pasa si tienes una clase de Resumen con solo métodos abstractos? ¿Cómo sería eso diferente de una interfaz? Creo que no hay diferencia si solo tiene método. entonces por qué Microsoft ha traído dos cosas. La herencia es tener-una relación, ¿qué implementación de interfaz? –

5

Tiendo a pensar en las interfaces como un contrato de comportamiento. Las interfaces como IComparable e IEnumerable son ejemplos clásicos.

En el ejemplo que proporcionó, IHuman e IEngineer no son realmente comportamientos.

2

Los diseñadores de .NET Framework usan interfaces para designar una relación "tiene una" (o "puede hacer"), mientras que "is a" se implementa utilizando la herencia.

El fundamento de esto se puede encontrar en la sección Choosing Between Classes and Interfaces de la Guía del programador de .NET Framework:

Una interfaz define las firmas para un conjunto de miembros que los implementadores deben proporcionar. Las interfaces no pueden proporcionar detalles de implementación para los miembros.

Por lo tanto, dado que sus clases de ejemplo "Programador" e "Ingeniero" probablemente vendrían con su propia funcionalidad específica, se implementarían más adecuadamente utilizando la herencia.

2

En realidad es por eso que la mayor parte de la interfaz son las capacidades y no los nombres de modo que tenga

IComparable, ITestable, IEnumerable

y

humana, animal, perro, etc

De todos modos, como ya se ha mencionado, tiene que ser pragmático, tengo una regla general cuando estoy codificando: Nunca deje que conceptos, convenciones o prácticas estándar se interpongan para hacer el trabajo, mejor sea pragmático que académico

así que si está seguro de que las interfaces realmente se ajustan mejor a su diseño, adelante, no se preocupe por una pregunta como esta.

4

encontrado esta pregunta bastante tarde pero quería meter su cuchara.

interfaces en C# tienen una relación es-un, pero no es-un-objeto. Más bien, es-una-implementación.

En otras palabras, para Foo clase que implementa IBar, la siguiente prueba:

Foo myFoo = new Foo(); 
return myFoo is IBar; 

vuelve literalmente cierto. También puede decir,

IBar bar = myArrayList[3] as IBar; 
Foo foo = bar as Foo; 

O, si un método requiere un IBar, puede pasar un Foo.

void DoSomething(IBar bar) { 
} 

static void Main() { 
    Foo myFoo = new Foo(); 
    DoSomething(myFoo); 
} 

Obviamente, un IBar no tiene implementación en sí mismo, por lo que la relación de hacer las cosas también se aplica.

interface IBar { void happy(); } 
class Foo : IBar 
{ 
    void happy() 
    { 
     Console.Write("OH MAN I AM SO HAPPY!"); 
    } 
} 
class Program 
{ 
    static void Main() 
    { 
     IBar myBar = new Foo(); 
     myBar.happy(); 
    } 
} 

Pero, para el caso, lo mismo ocurre con la herencia de objetos; un objeto de la clase Foo que hereda la clase La barra tiene una relación de cosas que se pueden hacer, así como una relación is-a, de la misma manera que la interfaz. Es solo que su implementación fue pre-construida para eso.

La verdadera pregunta es, es-a- lo, can-do- lo? Un objeto de la clase heredada es-a- [instancia primaria] y CAN-do- [comportamiento de los padres], mientras que una implementación de una interfaz es-an- [implementación de la interfaz] y por lo tanto puede-do- [ el comportamiento de la interfaz].

En la mayoría de los casos donde se utiliza una relación programática como las enumeradas anteriormente, solo se evalúa la interfaz, por lo que tanto una clase heredada como una interfaz implementada comparten las mismas cualidades es-a y puede hacerlo.

HTH, Jon

Cuestiones relacionadas