2010-02-08 25 views
9

Me gustaría saber el uso significativo de la interfaz. He leído muchos artículos pero no entiendo claramente el concepto de interfaz.Importancia de las interfaces C#

He escrito un pequeño programa. He definido la interfaz Itest.Class(Manager) ha implementado el Interface.Another class(Employee) no ha implementado la interfaz. Pero definió el mismo método (DoSomething()) en la interfaz en la clase (Employee). Puedo llamar al método desde el objeto de la clase. Entonces, ¿por qué debería ir e implementar la interfaz? Puedo implementar directamente el método en una clase y llamar al método. ¿Por qué debería dar un paso adicional para implementar el método en una interfaz y luego heredar la interfaz por clase? Sé que la interfaz admite herencia múltiple, pero no estoy usando herencia múltiple en este ejemplo.

Gracias por cualquier idea o sugerencia.

public interface Itest 
{ 
    void DoSomething(); 
} 

public class Manager:Itest 
{ 
    public void DoSomething() 
    { 
     Console.WriteLine("test...."); 
    } 

} 
class Employee 
{ 
    public void DoSomething() 
    { 
     Console.WriteLine("test...."); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Manager m = new Manager(); 
     m.DoSomething(); 
     Employee e = new Employee(); 
     e.DoSomething(); 
     Console.ReadLine(); 
    } 
} 
+0

¿Por qué no elegir un ejemplo donde hay herencia múltiple, por ej. un administrador admite 'ITest' y' ISerializable' y 'ICloneable', etc. ¡Entonces sin duda responderá a su propia pregunta! –

+0

So Interfaz utilizada básicamente para implementar Herencia múltiple. ningún otro uso. – Shikha

+3

Esto es casi duplicado de http://stackoverflow.com/questions/2151959/using-interface-variables - las respuestas allí pueden responder a su pregunta (vea también los comentarios a la respuesta aceptada). – itowlson

Respuesta

0

Por supuesto, puede implementar el método declarado en la interfaz sin implementar la interfaz. Simple puesto, las interfaces solo se aseguran de que no se olvide (le darán errores de compilación si alguno de los miembros de la interfaz no se implementa).

+0

Lo mismo ocurre con los métodos abstractos en una clase base abstracta. –

+0

Sí, eso es cierto. La diferencia es que la interfaz solo proporciona la descripción del método cuando la clase abstracta puede tener un código que hace algo. – RaYell

+0

Los métodos abstractos en la clase abstracta (ver mi primer comentario) solo dan la descripción del método, exactamente como los métodos en una interfaz. La única capacidad exclusiva de las interfaces es la herencia múltiple. –

10

Las interfaces se utilizan para la abstracción (las clases abstractas también se usan para esto, pero normalmente contienen algunas implementaciones destinadas a la reutilización).

En C# permiten el uso de herencia múltiple, lo que significa que puede implementar muchas interfaces diferentes en una clase.

Si tiene muchas implementaciones diferentes de una interfaz, puede sustituirlas por otra, siempre que use la declaración de interfaz.

Por ejemplo:

IAnimal puede ser implementado por Cat y por Dog. En otro código, desea llamar al método Talk que se declara en la interfaz. Su código no tiene que importar si se trata de un objeto Cat o un objeto Dog. Puede agregar Duck o Human y no cambiar ese fragmento de código.

Esto también es útil cuando se prueba el código con objetos simulados, por lo que un objeto simple puede ser sustituido por el real para fines de prueba.

Algunas interfaces se usan como marcadores para que la reflexión pueda recogerlas fácilmente (por ejemplo, la interfaz ISerializable, marcando una clase como serializable).

+0

"Las interfaces se utilizan para la abstracción", también lo son las clases/métodos abstractos, de ahí el nombre. –

+1

Una interfaz es el concepto más abstracto que existe en la programación OO. Las clases abstractas son más concretas que las interfaces y generalmente implementan algunas interfaces. Lo que importa es el concepto, no cómo un lenguaje específico llama un concepto. – Trap

+1

+1 por mencionar las pruebas, que es mi razón principal para usar interfaces, así que no necesito datos reales en una base de datos para realizar pruebas. Simplemente ejecuto un simulacro usando Moq (y otros hacen lo mismo con Rhino, NMock2 et al). – Fenton

14

Las interfaces le permiten ordenar el uso de la herencia múltiple. En su ejemplo, le permitiría colocar una instancia de Empleado o Administrador en la misma variable, y luego llamar al DoSomething en esa variable, con la llamada al método que se envía a la instancia a la que hace referencia actualmente esa variable. Por ejemplo:

public interface IEmployee { 
    void DoSomething(); 
} 
// assume Manager and Employee both implement IEmployee 

IEmployee ie = new Manager(); 
ie.DoSomething(); // calls Manager.DoSomething() 
ie = new Employee(); 
ie.DoSomething(); // calls Employee.DoSomething() 

Si no utiliza interfaces, habría que hacer:

object o; 

// assign Manager or Employee (or something else!) to o 

if (o is Manager) 
    ((Manager)o).DoSomething(); 
else if (o is Employee) 
    ((Employee)o).DoSomething(); 

Una interfaz define un contrato , y siempre que una instancia que implementa la interfaz que Don No importa lo que realmente es en tiempo de ejecución. Puede hacer que la misma clase implemente múltiples interfaces y luego usar instancias de esa clase en todas las variables de esas interfaces.No podría usar el mismo para las clases abstractas, ya que una clase solo puede heredar una clase por vez.

Un ejemplo en el que estoy usando interfaces de ahora es definir un modelo de objetos - Tengo las interfaces para diferentes propiedades (IHasStorage, IHasPrivileges, IHasCheezburger), entonces las clases que representan los objetos concretos poner en práctica lo que y sin embargo son muchas interfaces apropiado para que las propiedades de clase

+0

+1 porque la compatibilidad con MI es el valor * único * de las interfaces (en comparación con las clases/métodos abstractos). –

+4

Y, para amplificar, su segundo fragmento de código * todavía * no haría el trabajo porque no podría manejar cosas-que-podría-hacer-Hacer Algo que no fueron anticipadas por el autor de la rutina de la llamada. Si más adelante introduzco una clase de Contratista, el enfoque basado en la interfaz simplemente sigue funcionando, pero la rutina 'if (o es X)' debe actualizarse para manejar el nuevo caso. – itowlson

+0

El propietario de la clase instanciada debe almacenarlo como el tipo más derivado, es decir, "Manager m = new Manager();". De lo contrario, borrará todas las demás propiedades que podrían ser importantes. p.ej. si el administrador implementa IDisposable. Los métodos no propietarios deben usar el tipo menos derivado necesario. – adrianm

2

Cuando se agrega la interfaz con el empleado las dos clases se hacen compatible a través de la interfaz:

public class Manager:Itest { ... } 

class Employee:Itest { ... } 

static void ShowSomething(Itest test) 
{ 
    test.DoSomething(); 
} 

static void Main(string[] args) 
{ 

    Manager m = new Manager();    
    Employee e = new Employee(); 

    ShowSomething(m); 
    ShowSomething(e); 
} 

Tome un vistazo a cómo el BCL utiliza la interfaz, para empezar a mirar hacia arriba IDisposable, ISerializable, IComprab Le IEnumerable y

1

La herencia de interfaz que dan la posibilidad de cambiar su aplicación con otra clase u objeto sin romper su código. La interfaz significa que usted hace un contrato con los clientes de su código que le proporcionará cierta funcionalidad y no tienen que saber qué clase particular llamar para esto. La interfaz agrega una capa de abstracción, por lo que sus clientes de su código no dependerán de cómo implemente la solución. Simplemente saben que los proporcionará, lo que está en la interfaz. Se proporciona

+0

Esto es cierto para las clases abstractas, excepto que con las interfaces es * peor *. Si agrega un método a una clase abstracta, puede proporcionar una implementación predeterminada. Si prueba lo mismo con una interfaz, rompe todas las bibliotecas que la implementan. –

+0

Las clases abstractas tienen diferentes propósitos. Para codificar algún comportamiento que es común para la jerarquía y para evitar la duplicación de código. – anthares

1

Una buena analogía para interfaces Matthew Cochran

"Este hacer para una mucho más fácil 'mundo de código' en el que navegar. Imagínese si en lugar de aprender a conducir un automóvil y luego poder conducir cualquier automóvil, tuvimos que aprender a manejar cada instancia de cada automóvil en el que nos metimos. Sería realmente ineficiente si después de aprender a conducir el Ford Pinto tuviéramos que comenzar todo de nuevo en orden descubrir el Mustang. Una forma mucho más eficiente es lidiar con los autos. interfaz: el volante, los intermitentes, el acelerador y el freno. De esta manera, no importa lo que se implementó en el backend de la interfaz, que no me importa, porque al final se suscribe el contrato básico del coche y así es como vamos a tratar con él (a través de la interfaz) 0,2

Junto con la explicación general anterior, la mayor parte del patrón de diseño de software moderno, mucho dependen de interfaces, tales como Dependendency inyección

Considere este ejemplo:

tiene una clase que es capaz de reproducir archivos multimedia (mp3). Le das esa clase a tu amigo que intenta reproducir archivos de tipo MPEG. No sería posible para él hacerlo sin hacer cambios significativos en su clase.

public class MusicPlayer 
    { 
     void Play(Mp3 _mp3File){} 
    } 

consideran que este

En lugar de paso del tipo de archivos MP3 para reproducir Método lo que si pasa este método, una deriva de una interfaz de tipo MediaType.

public interface MediaType { } 

    public class Mp3 : MediaType 
    { } 

    public class MPEG : MediaType 
    { } 

y clase:

public class MusicPlayer 
    { 
     void Play(MediaType _mediaFile){} 
    } 

En este escenario, puede derivar otro tipo de archivo multimedia y de MediaType como MPEG y sucedió que con el método de reproducción y que estará feliz de aceptarlo y reproducirlo para usted (siempre que haya lógica).

public class TestPlayers 
    { 
     public void PlayMedia() 
     { 
      MusicPlayer musicPlayer = new MusicPlayer(); 
      musicPlayer.Play(new Mp3()); 
      musicPlayer.Play(new MPEG()); 
     }  
    } 

Hope esto ayuda

+0

Todo lo anterior es igualmente cierto para las clases abstractas. –

+0

Earwicker: ¿Está seguro de que podemos hacer lo anterior con la clase abstracta. ¿Tiene algún ejemplo o enlace ... – Shikha

1

interfaces son útiles en un poco escenarios más complejos, por ejemplo

(1) Necesita herencia múltiple (en C# no puede heredar de 2 clases), p. tienes interfaces IProduct, IDisposable. No es necesario eliminar todos los productos, por lo que no tiene sentido implementarlo en todos los productos, etc.

(2) Cuando utiliza la inyección de dependencia (inversión de control) y un marco de burla (por ejemplo, RhinoMocks) para pruebas unitarias, entonces tienes que trabajar con interfaces, de lo contrario tu marco de burla no funcionará.

+0

Si no estoy usando MI, Interface no tiene ningún uso? – Shikha

1

Ya sabes, es gracioso que estuve hablando con uno de nuestros desarrolladores sobre este mismo tema hoy.

La manera más fácil para mí de explicar qué es una interfaz y su usabilidad es el siguiente ejemplo.

interface IGraphicsRenderer 
{ 
    Render(List<Triangle> triangles); 
} 

entonces usted podría tener 2 tipos de motores de renderizado, Direct3D u OpenGL

class Direct3DRenderer : IGraphicsRenderer 
{ 
    public void Render(List<Triangle> triangles); 
} 

class OpenGLRenderer: IGraphicsRenderer 
{ 
    public void Render(List<Triangle> triangles); 
} 

Para demostrar su utilidad, es posible que tenga algo en la línea de

IGraphicsRenderer renderer = new Direct3DRenderer(); 
renderer.Render(foo); 

para cambiar el renderizador, todo lo que necesita hacer es cambiar la inicialización.

IGraphicsRenderer renderer = new OpenGLRenderer(); 
1

Cuando tiene demasiadas clases que manejan desde una clase de interfaz, asegúrese de que todas ellas implementen un Método.

Entonces, si los cambios de interfaz (por ejemplo:

 public Interface IAnimal 
      { 
       public void Talk(); 
       public void Eat(); 
      } 

y luego se agregan otro método

 public Interface IAnimal 
      { 
       public void Talk(); 
       public void Sleep(); 
       public void Eat(); 
      } 

entonces se puede asegurar, que todos ellos se implemente el método del sueño() si. tiene demasiadas clases que derivan de IAnimal Inteface, entonces usted debe implementar Sleep() para todas ellas. Esto lo ayudará a extender lo más fácilmente posible sus clases derivadas

0

Supongo que quieres una respuesta muy simple.

Hay 2 tipos de herencia:

  • TIPO 1: herencia de interfaz (en términos simples: cuando se hereda el exterior de la clase )
  • tipo 2: herencia de implementación (cuando el dentro de la clase se hereda)

Si se escribe

class MyClass : Base {} 

está utilizando tipo 1 y 2. Sin embargo, si se implementa una interfaz que es clara tipo 1.

tipo 1 es para uso polimórfica y tipo 2 es para la reutilización de código.

Así que la conclusión es que si desea utilizar el polimorfismo pero

  • no desea proporcionar cualquier aplicación
  • o simplemente no pueden hacerlo. Sobre todo en caso de herencia múltiple - Nota: C++ permite que, se deduce otra filosofía

interfaces son para ti :)

hay otros usos (por ejemplo, forzar la implementación de un método), pero en mi opinión este es el punto.

0

Las interfaces son para diseños. La implementación real sigue lo que se define en el diseño (interfaz de lectura). El concepto de interfaz le da a uno la flexibilidad para diseñar un sistema sin entrar en los detalles de la implementación, o mantener el diseño extensible implementando las interfaces en el futuro. Esto también se conoce como abstracción.

Si bien la interfaz brinda flexibilidad a la hora de diseñar, impone la restricción en el momento de la implementación. Cualquier implementación de una interfaz debe ser completa, significa que es necesario implementar todas las especificaciones definidas en la interfaz en el momento de la implementación. También la otra flexibilidad en este momento es que uno puede implementar múltiples interfaces en una clase.

Este es un concepto muy sólido que proporciona un alto grado de flexibilidad en el momento del diseño y se asegura de que la implementación no rompa el diseño.

4

La herencia de implementación modela una relación "IS A KIND OF", mientras que la herencia de interfaz modela una relación "CAN BEHAVE LIKE". No es coincidencia que muchos de los nombres de la interfaz BCL terminen con "-able", que representa la capacidad de hacer algo. Para demostrarlo, la imagen del código siguiente:

class Person 
{ 
    public string Name{get;set;} 
    public void Walk() {/*code elided*/} 
} 

class Employee : Person 
{ 
    public int Id{get;private set;} 
} 

Es evidente que un empleado "es una especie de" Persona. Todos los empleados son personas, por lo tanto, todos tienen un nombre y pueden caminar(). Por supuesto, hacer Persona o Empleado abstracto, no cambia el hecho de que todos los empleados son personas.

Ahora vamos a ponernos un poco más abstractos y hablar sobre el concepto de ser un vehículo. Lo esencial para que una cosa sea un vehículo es que debe poder moverse y detenerse. Puede incluir dirección y transporte de pasajeros, pero lo mantengo muy abstracto.

Pensemos en algunas cosas que son vehículos. Un automóvil, por supuesto, pero ¿qué tal una persona? Pueden moverse y detenerse (y cuando les doy a mis sobrinos y sobrinas a cuestas también llevo pasajeros). ¿Una silla blanca? Siempre estoy entreteniéndome en la oficina. También soy un entusiasta marinero y uso el viento para acelerar y desacelerar mi vehículo.

No puede modelar este tipo de relación utilizando la herencia de implementación, porque tiene muchas cosas diferentes que "pueden actuar como" un vehículo pero que no necesariamente heredan de la misma clase base.

Un pogostick (con disculpas a los pogo-ers profesionales) ES UN TIPO DE Juguete, pero PUEDE ACTUAR COMO un vehículo. No todos los juguetes son vehículos. Una persona no tiene ninguna relación con un automóvil, aparte del hecho de que PUEDE ACTUAR como vehículo.

interface IVehicle 
{ 
    void Move(); 
    void Stop(); 
} 

class Toy{} 

class PogoStick : Toy, IVehicle 
{ 
    public void Move(){ /* boing boing */} 
    public void Stop(){ /* fall over */} 
} 

class Car: IVehicle 
{ 
    public void Move(){ /* vroom vroom */} 
    public void Stop(){ /* <screeeech!> */} 
} 

class Person : IVehicle 
{ 
    public string Name{get;set;} 
    public void Walk() {/*code elided*/} 
    void IVehicle.Move() { Walk(); } 
    void IVehicle.Stop() { /*whatever!*/} 
} 

class Program 
{ 
    static void Main() 
    { 
    IVehicle[] vehicles = new IVehicle[3]; 
    vehicles[0] = new PogoStick(); 
    vehicles[1] = new Car(); 
    vehicles[2] = new Employee(); //implements IVehicle because it IS A KIND OF Person 

    vehicles.ForEach(v => v.Move()); 

    //it's worth pointing out that 
    vehicles[2].Stop(); 
    //works fine, but 
    Person p = new Person(); 
    p.Move(); 
    //won't, as I explicitly implemented the interface, meaning I can only get at the 
    //methods via a reference to the interface, not to the implementing class. 
    } 
} 

Para usar un ejemplo de .NET, ¿qué tiene en común una cadena en común con una lista? No mucho, excepto que pueda "foreach" ambos:

class Demo 
{ 
    static void Main() 
    { 
    string s = "Hello!"; 
    List<Employee> payroll = new List<Employee>(); 

    for each (var item in s) 
    { 
     Console.WriteLine(item); 
    } 

    for each (var item in payroll) 
    { 
     Console.WriteLine(item); 
    } 
} 

La clase base común para la cadena y la lista es objeto, pero no todos los objetos son "foreach-poder", por lo que no tiene que estar pasando algo más. A saber, que ambos implementan la interfaz IEnumerable (¡hay que -able!)

Cuestiones relacionadas