¿Por qué son útiles las interfaces?

158

He estado estudiando y codificando en C # por algún tiempo. Pero aún así, no puedo entender la utilidad de las interfaces. Traen muy poco a la mesa. Aparte de proporcionar las firmas de función, no hacen nada. Si puedo recordar los nombres y la firma de las funciones que se necesitan para implementar, no hay necesidad de ellas. Están allí solo para asegurarse de que dichas funciones (en la interfaz) se implementen en la clase heredada.

C # es un gran lenguaje, pero a veces le da la sensación de que primero Microsoft crea el problema (no permite la herencia múltiple) y luego proporciona la solución, que es bastante tediosa.

Esa es mi comprensión, que se basa en una experiencia de codificación limitada. ¿Cuál es tu opinión sobre las interfaces? ¿Con qué frecuencia los usas y qué te hace hacerlo?

Pankaj Upadhyay
fuente
55
"Si puedo recordar los nombres y la firma de las funciones que se necesitan para implementar, no hay necesidad de ellas". Esta afirmación me hace sospechar que debería analizar un poco más las ventajas de los lenguajes estáticamente escritos .
Steven Jeuris
37
Olvídate de C #, olvida Java, olvida el lenguaje. Simplemente está pensando en términos de OO. Te animo a que recojas material de lectura de personas como Robert C. Martin, Martin Fowler, Michael Feathers, The Gang of Four, etc., ya que te ayudará a expandir tu pensamiento.
Anthony Pegram
27
Me llevó más de dos años entender realmente para qué interfaces son buenas. Mi sugerencia: estudiar Patrones de diseño. Como la mayoría de ellos se basan en interfaces, comprenderá rápidamente por qué son tan útiles.
Oliver Weiler,
37
Tienes mucho que aprender amigo.
ChaosPandion
6060
@ChaosPandion todos tenemos mucho que aprender
kenwarner

Respuestas:

151

Están allí solo para asegurarse de que dichas funciones (en la interfaz) se implementen en la clase heredada.

Correcto. Ese es un beneficio suficientemente impresionante para justificar la función. Como han dicho otros, una interfaz es una obligación contractual de implementar ciertos métodos, propiedades y eventos. El beneficio convincente de un lenguaje de tipo estático es que el compilador puede verificar que se cumpla realmente un contrato en el que se basa su código.

Dicho esto, las interfaces son una forma bastante débil de representar obligaciones contractuales. Si desea una forma más sólida y flexible de representar las obligaciones contractuales, consulte la función Contratos de código que se incluye con la última versión de Visual Studio.

C # es un gran lenguaje, pero a veces le da la sensación de que primero Microsoft crea el problema (no permite la herencia múltiple) y luego proporciona la solución, que es bastante tediosa.

Bueno, me alegra que te guste.

Todos los diseños de software complejos son el resultado de sopesar las características en conflicto entre sí y de tratar de encontrar el "punto óptimo" que brinde grandes beneficios por pequeños costos. A través de una experiencia dolorosa, hemos aprendido que los lenguajes que permiten la herencia múltiple con el propósito de compartir la implementación tienen beneficios relativamente pequeños y costos relativamente altos. Permitir la herencia múltiple solo en las interfaces, que no comparten detalles de implementación, brinda muchos de los beneficios de la herencia múltiple sin la mayoría de los costos.

Eric Lippert
fuente
Estaba leyendo "Microsoft crea el problema al no permitir la herencia múltiple" y pensé que Eric Lippert tendría algo que decir al respecto.
configurador
Más relevante para esta respuesta: Eric, estás refiriendo al solicitante a los contratos de código, pero están lamentablemente incompletos; El verificador estático no puede hacer cumplir cualquier otra cosa que no sean los contratos más básicos. Intenté usar Code Contract en un proyecto pequeño; Agregué cientos de líneas para todos y cada uno de los métodos que especifican todo lo que pude sobre entrada y salida, y sin embargo, tuve que agregar tantas Assumellamadas, para casos como miembros de matriz o enumeración. Después de agregar todo y ver el desorden estáticamente verificado que tuve, volví al control de la fuente porque redujo la calidad de mi proyecto.
configurador
17
@configurator: Están incompletos porque no pueden completarse; La verificación estática del programa con contratos arbitrarios es equivalente a resolver el problema de detención. (Por ejemplo, podría escribir un contrato de código que diga que los argumentos de un método deben ser un contraejemplo del último teorema de Fermat; pero el verificador estático no podrá verificar que no existan tales argumentos). tiene que usarlo juiciosamente si espera que el verificador estático complete su trabajo antes de la muerte por calor del universo. (Si su queja es que el BCL no está suficientemente anotado: estoy de acuerdo.)
Eric Lippert
2
Espero que se dé cuenta de que cuando un método promete que la matriz o enumeración de resultados no contiene nulo, el método que usa puede usar los valores en lugares que no permiten nulos. Esa es la única cosa que esperaba que hiciera y no fue así, y era demasiado importante para poder usarse sin ella; cualquier otra cosa es solo una bonificación. Dicho esto, sé que la verificación estática no puede completarse, por lo que creo que no es una buena alternativa para confiar en los contratos.
configurador
99
+1 para "Bueno, me alegro de que te guste". Y todas las demás cosas también.
Robert S.
235

ingrese la descripción de la imagen aquí

Entonces, en este ejemplo, el PowerSocket no sabe nada más sobre los otros objetos. Todos los objetos dependen de la energía proporcionada por el PowerSocket, por lo que implementan IPowerPlug y, al hacerlo, pueden conectarse a él.

Las interfaces son útiles porque proporcionan contratos que los objetos pueden usar para trabajar juntos sin necesidad de saber nada más el uno del otro.

revs Slomojo
fuente
44
El objeto inferior izquierdo no parece que implemente IPowerPlug =)
Steven Striga
100
¡Maldición, pero tendremos que usar un patrón de Adaptador para usar IPowerPlug en diferentes países!
Steven Jeuris
La manipulación de un dispositivo para evitar la interfaz no es segura (pero algunas personas todavía lo hacen a menudo citando el rendimiento como una excusa no probada) y es probable que provoque incendios.
YoungJohn
44
Esta respuesta es simplemente increíble ...
Mario Garcia
Solo señalar esta respuesta no dice, en este ejemplo en particular, por qué usar una interfaz sería preferible a la herencia. Alguien nuevo en las interfaces podría preguntarse por qué no todas heredan de, por ejemplo, MainsPoweredDevice que proporciona toda la funcionalidad de conexión, y el socket acepta todo lo derivado de MainsPoweredDevice.
ingrediente_15939
145

Aparte de proporcionar las firmas de función, no hacen nada. Si puedo recordar los nombres y la firma de las funciones que se necesitan para implementar, no hay necesidad de ellas

El objetivo de las interfaces no es ayudarlo a recordar qué método implementar, está aquí para definir un contrato . En foreach P.Brian.Mackey ejemplo (que resulta ser incorrecto , pero no nos importa), IEnumerable define un contrato entre foreach y cualquier cosa enumerable. Dice: "Quienquiera que sea, siempre que cumpla con el contrato (implemente IEnumerable), le prometo que iteraré sobre todos sus elementos". Y eso es genial (para un lenguaje no dinámico).

Gracias a las interfaces, puede lograr un acoplamiento muy bajo entre dos clases.

David
fuente
No me gusta usar el término "tipear pato" porque significa cosas diferentes para diferentes personas. Utilizamos la coincidencia de patrones para el bucle "foreach" porque cuando se diseñó, IEnumerable <T> no estaba disponible. Utilizamos la coincidencia de patrones para LINQ porque el sistema de tipo C # es demasiado débil para capturar el "patrón de mónada" que necesitamos; necesitarías algo como el sistema de tipos Haskell.
Eric Lippert
@Eric: ¿La "coincidencia de patrones" no tiene el mismo problema? Cuando lo escucho pienso en F # / Scala / Haskell. Pero supongo que es una idea más amplia que escribir pato.
Daniel
@Daniel: Sí, supongo que sí. ¡Es seis de una y media docena de la otra, supongo!
Eric Lippert
36

Las interfaces son la mejor manera de mantener construcciones bien desacopladas.

Al escribir pruebas, encontrará que las clases concretas no funcionarán en su entorno de prueba.

Ejemplo: desea probar una clase que depende de una clase de servicio de acceso a datos . Si esa clase está hablando con un servicio web o una base de datos, su prueba unitaria no se ejecutará en su entorno de prueba (además se ha convertido en una prueba de integración).

¿Solución? Use una interfaz para su servicio de acceso a datos y simule esa interfaz para que pueda probar su clase como una unidad.

Por otro lado, WPF y Silverlight no juegan en absoluto con las interfaces cuando se trata de encuadernación. Esta es una arruga bastante desagradable.

Sheldon Warkentin
fuente
2
¡escucha Escucha! Las interfaces se inventaron para resolver otros problemas, como el polimorfismo. Sin embargo, para mí, se ponen de manifiesto cuando implementan un patrón de inyección de dependencia.
Andy
29

¡Las interfaces son la columna vertebral del polimorfismo (estático)! La interfaz es lo que importa. La herencia no funcionaría sin interfaces, ya que las subclases básicamente heredan la interfaz ya implementada del padre.

¿Con qué frecuencia los usas y qué te hace hacerlo?

Muy a menudo. Todo lo que necesita ser conectable es una interfaz en mis aplicaciones. Muchas veces tiene clases no relacionadas que necesitan proporcionar el mismo comportamiento. No puede resolver tales problemas con la herencia.

¿Necesita diferentes algoritmos para realizar operaciones con los mismos datos? ¡Use una interfaz ( vea el patrón de estrategia )!

¿Quieres usar diferentes implementaciones de listas? Código contra una interfaz y la persona que llama no necesita preocuparse por la implementación.

Se ha considerado una buena práctica (no solo en OOP) codificar contra interfaces por años, por una sola razón: es fácil cambiar una implementación cuando te das cuenta de que no se ajusta a tus necesidades. Es bastante engorroso si intenta lograrlo solo con herencia múltiple o se reduce a crear clases vacías para proporcionar la interfaz necesaria.

Falcon
fuente
1
Nunca he oído hablar de la polimorfia, ¿te refieres al polimorfismo?
Steven Jeuris
1
Dicho esto, si Microsoft permitió la herencia múltiple en primer lugar, no habría habido ninguna razón para la existencia de interfaces
Pankaj Upadhyay
10
@Pankaj Upadhyay: La herencia múltiple y las interfaces son dos pares de zapatos diferentes. ¿Qué sucede si necesita una interfaz de dos clases no relacionadas con un comportamiento diferente? No se puede resolver eso por herencia múltiple. DEBE implementarlo por separado de todos modos. Y luego necesitará algo para describir la interfaz para proporcionar un comportamiento polimórfico. La herencia múltiple es un callejón sin salida para caminar en muchos casos, y es demasiado fácil dispararse en el pie tarde o temprano.
Falcon
1
Vamos a simplificar Si mi interfaz implementa dos funciones, Pantalla y Comentario, y tengo una clase que las implementa. Entonces, ¿por qué no elimino la interfaz y uso las funciones directamente? Lo que estoy diciendo es que simplemente le proporcionan los nombres de las funciones que se necesitan para implementar. Si uno puede recordar esas funciones, ¿por qué crear una interfaz?
Pankaj Upadhyay
99
@ Pankaj, si eso es todo para lo que necesita la interfaz, entonces no la use. Utiliza una interfaz cuando tienes un programa que quiere ignorar todos los aspectos de la clase y acceder a él por su Tipo base, es decir, la interfaz. No necesitan conocer ninguna de las subclases, solo que es del tipo de la interfaz. Como tal, puede llamar al método implementado de la subclase a través de la referencia a la interfaz del objeto. Esto es herencia básica y cosas de diseño. Sin él, también podría usar C. Incluso si no lo usa explícitamente, el marco no funcionaría sin él.
Jonathan Henson el
12

Probablemente lo haya usado foreachy lo haya encontrado como una herramienta de iteración bastante útil. ¿Sabía que requiere una interfaz para funcionar, IEnumerable ?

Ese es ciertamente un caso concreto que habla de la utilidad de una interfaz.

P.Brian.Mackey
fuente
55
En realidad, foreach no requiere IEnumerable: msdn.microsoft.com/en-us/library/9yb8xew9%28VS.80%29.aspx
Matt H
1
He estudiado todo eso, pero es como sostener la oreja con la otra mano. Si se permitiera la herencia múltiple, la interfaz habría sido una opción lejana.
Pankaj Upadhyay
2
Las interfaces SON herencia múltiple, algo que a menudo se olvida. Sin embargo, no permiten la herencia múltiple de comportamiento y estado. Los mixins o rasgos permiten la herencia múltiple del comportamiento, pero no el estado compartido que causa problemas: en.wikipedia.org/wiki/Mixin
Matt H
@Pankaj, fuera del tema, pero ¿te importa si te pregunto cuál es tu idioma nativo? "Sostener la oreja con la otra mano" es un gran modismo y tenía curiosidad de dónde viene.
Kevin
3
@Repartidor de hielo. LOL .... Soy de la India. Y aquí es un idioma común que refleja hacer las cosas fáciles de la manera difícil.
Pankaj Upadhyay
11

Las interfaces son para codificar objetos como un enchufe para el cableado doméstico. ¿Soldarías tu radio directamente al cableado de tu casa? ¿Qué tal tu aspiradora? Por supuesto no. El enchufe y la toma de corriente en la que encaja forman la "interfaz" entre el cableado de su casa y el dispositivo que necesita energía. El cableado de su casa no necesita saber nada sobre el dispositivo, aparte de que utiliza un enchufe con conexión a tierra de tres terminales y requiere energía eléctrica a 120 VCA <= 15A. Por el contrario, el dispositivo no requiere un conocimiento arcano de cómo está conectada su casa, además de que tiene una o más salidas de tres clavijas convenientemente ubicadas que proporcionan 120VCA <= 15A.

Las interfaces realizan una función muy similar en el código. Un objeto puede declarar que una variable particular, parámetro o tipo de retorno es de un tipo de interfaz. La interfaz no se puede instanciar directamente con una newpalabra clave, pero mi objeto puede recibir o encontrar la implementación de esa interfaz con la que tendrá que trabajar. Una vez que el objeto tiene su dependencia, no tiene que saber exactamente cuál es esa dependencia, solo tiene que saber que puede llamar a los métodos X, Y y Z en la dependencia. Las implementaciones de la interfaz no tienen que saber cómo se utilizarán, solo deben saber que se espera que proporcionen los métodos X, Y y Z con firmas particulares.

Por lo tanto, al abstraer varios objetos detrás de la misma interfaz, proporciona un conjunto común de funcionalidades a cualquier consumidor de objetos de esa interfaz. No tiene que saber que el objeto es, por ejemplo, una Lista, un Diccionario, una Lista enlazada, una Lista ordenada o lo que sea. Como sabe que todos estos son IEnumerables, puede usar los métodos de IEnumerable para revisar cada elemento de estas colecciones de uno en uno. No tiene que saber que una clase de salida es ConsoleWriter, FileWriter, NetworkStreamWriter o incluso un MulticastWriter que toma otros tipos de escritores; todo lo que tiene que saber es que son todos IWriters (o lo que sea), y por lo tanto tienen un método de "Escritura" en el que puede pasar una cadena, y esa cadena se generará.

KeithS
fuente
7

Si bien es claramente un placer para el programador (al principio, al menos) tener herencia múltiple, esta es una omisión casi trivial, y usted (en la mayoría de los casos) no debe confiar en la herencia múltiple. Las razones para esto son complejas, pero si realmente quieres aprender al respecto, considera la experiencia de los dos lenguajes de programación más famosos (según el índice TIOBE ) que lo admiten: C ++ y Python (3º y 8º respetablemente).

En Python, se admite la herencia múltiple, pero los programadores la malinterpretan casi universalmente y decir que usted sabe cómo funciona significa leer y comprender este documento sobre el tema: Orden de resolución de métodos . Algo más, que sucedió en Python, es que las interfaces se introdujeron en el lenguaje: Zope.Interfaces.

Para C ++, busque en Google "Jerarquía de diamantes C ++" y contemple la fealdad que está a punto de cubrirlo. Los profesionales de C ++ saben cómo usar la herencia múltiple. Todos los demás generalmente solo juegan sin saber cuáles serán los resultados. Otra cosa que muestra cuán útiles son las interfaces es el hecho de que, en muchos casos, una clase podría necesitar anular completamente el comportamiento de sus padres. En tales casos, la implementación primaria es innecesaria y solo carga a la clase secundaria con la memoria para las variables privadas de la matriz, lo que puede no importar en la era de C #, pero es importante cuando se realiza una programación integrada. Si usa una interfaz, ese problema es inexistente.

En conclusión, las interfaces son, en mi opinión, una parte esencial de OOP, porque hacen cumplir un contrato. La herencia múltiple es útil en casos limitados, y generalmente solo para hombres que saben cómo usarla. Entonces, si eres un principiante, eres el que es tratado por la falta de herencia múltiple; esto te da una mejor oportunidad de no cometer un error .

Además, históricamente, la idea de una interfaz se basa mucho antes que las especificaciones de diseño C # de Microsoft. La mayoría de las personas consideran que C # es una actualización sobre Java (en la mayoría de los sentidos), y adivinan de dónde obtuvo C # sus interfaces: Java. Protocolo es una palabra más antigua para el mismo concepto, y es mucho más antiguo que .NET.

Actualización: Ahora veo que podría haber respondido una pregunta diferente: por qué las interfaces en lugar de herencia múltiple, pero esta parecía ser la respuesta que estabas buscando. Además, un lenguaje OO debe tener al menos uno de los dos, y las otras respuestas han cubierto su pregunta original.

George Penn.
fuente
6

Me resulta difícil imaginar un código C # limpio y orientado a objetos sin el uso de interfaces. Los usa siempre que desee imponer la disponibilidad de ciertas funciones sin obligar a las clases a heredar de una clase base específica, y esto permite que su código tenga el nivel relevante de acoplamiento (bajo).

No estoy de acuerdo con que la herencia múltiple sea mejor que tener interfaces, incluso antes de llegar a argumentar que la herencia múltiple viene con su propio conjunto de dolores. Las interfaces son una herramienta básica para habilitar el polimorfismo y la reutilización de código, ¿qué más se necesita?

Daniel B
fuente
5

Personalmente, amo la clase abstracta y la uso más que una interfaz. La principal diferencia viene con la integración con interfaces .NET como IDisposable, IEnumerable, etc. ... y con interoperabilidad COM. Además, la interfaz requiere un poco menos de esfuerzo para escribir que una clase abstracta, y una clase puede implementar más de una interfaz mientras que solo puede heredar de una clase.

Dicho esto, creo que la mayoría de las cosas para las que usaría una interfaz están mejor atendidas por una clase abstracta. Las funciones virtuales puras (funciones abstractas) le permiten obligar a un implementador a definir una función similar a la forma en que una interfaz obliga a un implementador a definir a todos sus miembros.

Sin embargo, normalmente usa una interfaz cuando no desea imponer un cierto diseño a la superclase, mientras que usaría una clase abstracta para tener un diseño reutilizable que ya esté implementado en su mayoría.

He usado interfaces extensamente con entornos de plugins de escritura usando el espacio de nombres System.ComponentModel. Son bastante útiles.

Jonathan Henson
fuente
1
Muy bien puesto! Supongo que te gustará mi artículo sobre clases abstractas. La abstracción lo es todo .
Steven Jeuris
5

Puedo decir que me relaciono con eso. Cuando comencé a aprender sobre OO y C #, tampoco obtuve interfaces. Está bien. Solo necesitamos encontrar algo que lo haga apreciar las conveniencias de las interfaces.

Déjame probar dos enfoques. Y perdóname por las generalizaciones.

Prueba 1

Digamos que eres un hablante nativo de inglés. Vas a otro país donde el inglés no es el idioma nativo. Necesitas ayuda. Necesitas a alguien que pueda ayudarte.

¿Pregunta: "Hey, naciste en los Estados Unidos?" Esto es herencia.

¿O preguntas: "Oye, hablas inglés"? Esta es la interfaz.

Si le importa lo que hace, puede confiar en las interfaces. Si te importa lo que es, confías en la herencia.

Está bien confiar en la herencia. Si necesita a alguien que hable inglés, le guste el té y le guste el fútbol, ​​es mejor que solicite un británico. :)

Prueba 2

Ok, intentemos con otro ejemplo.

Utiliza diferentes bases de datos y necesita implementar clases abstractas para trabajar con ellas. Pasará su clase a alguna clase del proveedor de DB.

public abstract class SuperDatabaseHelper
{
   void Connect (string User, string Password)
}

public abstract class HiperDatabaseHelper
{
   void Connect (string Password, string User)
}

¿Herencia múltiple, dices? Intenta eso con el caso anterior. No puedes El compilador no sabrá a qué método de Connect está intentando llamar.

interface ISuperDatabaseHelper
{
  void Connect (string User, string Password)
}

interface IHiperDatabaseHelper
{
   void Connect (string Password, string User)
}

Ahora, hay algo con lo que podemos trabajar, al menos en C #, donde podemos implementar interfaces explícitamente.

public class MyDatabaseHelper : ISuperDatabaseHelper, IHiperDatabaseHelper
{
   IHiperDataBaseHelper.Connect(string Password, string User)
   {
      //
   }

   ISuperDataBaseHelper.Connect(string User, string Password)
   {
      //
   }

}

Conclusión

Los ejemplos no son los mejores, pero creo que se entiende.

Solo "obtendrá" interfaces cuando sienta la necesidad de ellas. Hasta que pienses que no son para ti.

Luiz Angelo
fuente
El primer intento es lo que dio mi voto.
osundblad
1
Estoy usando totalmente la analogía entre el hablante estadounidense y el inglés de ahora en adelante. Eso es fantástico.
Bryan Boettcher el
¡Explicado de una manera más simple! Fantástico.
Aimal Khan
4

Hay 2 razones principales:

  1. Falta de herencia múltiple. Puede heredar de una clase base e implementar cualquier cantidad de interfaces. Esa es la única forma de "hacer" herencia múltiple en .NET.
  2. Interoperabilidad COM. Cualquier cosa que deba ser utilizada por tecnologías "antiguas" deberá tener interfaces definidas.
Tangurena
fuente
El punto 1 es definitivamente la razón y la razón desarrollada por los propios desarrolladores de microsoft
Pankaj Upadhyay
1
@Pankja En realidad, tomaron la idea de la interfaz de Java (como buena parte de las características de C #).
Oliver Weiler
3

El uso de interfaces ayuda a que el sistema permanezca desacoplado y, por lo tanto, sea más fácil de refactorizar, cambiar y volver a implementar. Es un concepto muy básico para la ortodoxia orientada a objetos y aprendí por primera vez cuando los gurús de C ++ crearon "clases abstractas puras" que son bastante equivalentes a las interfaces.

Jesse C. Slicer
fuente
El desacoplamiento es importante porque mantiene diferentes componentes de un sistema independientes entre sí. Que incluso los cambios de gran impacto en un componente no afectan a otros componentes. Piense en los enchufes de alimentación como una interfaz para su compañía de servicios públicos (especificando el voltaje y los pines físicos y el formato del enchufe). Gracias a esta interfaz, la utilidad puede cambiar completamente la forma en que producen energía (por ejemplo, usar tecnología solar), sin embargo, ninguno de los dispositivos notará ni mucho menos el cambio.
miraculixx
3

Las interfaces en sí mismas no son muy útiles. Pero cuando lo implementan clases concretas, ve que le brinda la flexibilidad de tener una o más implementaciones. La ventaja es que el objeto que usa la interfaz no necesita saber cómo van los detalles de la implementación real, eso se llama encapsulación.

Ronald
fuente
2

Se utilizan principalmente para la reutilización de código. Si codifica para la interfaz, puede usar una clase diferente que herede de esa interfaz y no romper todo.

También son muy útiles en los servicios web en los que desea que el cliente sepa lo que hace una clase (para que puedan consumirla) pero no desea darles el código real.

Tom Squires
fuente
2

Como programador / desarrollador joven, solo aprendiendo C # es posible que no vea la utilidad de la interfaz, porque puede escribir sus códigos usando sus clases y el código funciona bien, pero en el escenario de la vida real, construir una aplicación escalable, robusta y mantenible implica usar algunos arquitectónicos y patrones, que solo pueden hacerse posibles mediante el uso de la interfaz, por ejemplo, en la inyección de dependencia.

Adewole Ayobami
fuente
1

Una implementación del mundo real:

Puede lanzar un objeto como el tipo de interfaz:

IHelper h = (IHelper)o;
h.HelperMethod();

Puedes crear una lista de una interfaz

List<IHelper> HelperList = new List<IHelper>();

Con estos objetos puede acceder a cualquiera de los métodos o propiedades de la interfaz. De esta manera, puede definir una interfaz para su parte de un programa. Y construye la lógica a su alrededor. Entonces alguien más puede implementar su interfaz en sus objetos de negocios. Si los BO cambian, pueden cambiar la lógica de los componentes de la interfaz y no requieren un cambio en la lógica de su pieza.

SoylentGray
fuente
0

Las interfaces se prestan a la modularidad de estilo de complemento al proporcionar un mecanismo para que las clases comprendan (y se suscriban) a ciertos tipos de mensajes que entrega su sistema. Lo elaboraré.

En su aplicación, usted decide que cada vez que se carga o recarga un formulario, desea que se borren todas las cosas que alberga. Usted define una IClearinterfaz que implementa Clear. Además, usted decide que cada vez que el usuario presiona el botón Guardar, el formulario debe intentar mantener su estado. Por lo tanto, todo lo que cumple ISaverecibe un mensaje para persistir en su estado. Por supuesto, prácticamente hablando, la mayoría de las interfaces manejan varios mensajes.

Lo que distingue a las interfaces es que se puede lograr un comportamiento común sin herencia. La clase que implementa una interfaz dada simplemente comprende cómo comportarse cuando se emite un comando (un mensaje de comando) o cómo responder cuando se le consulta (un mensaje de consulta). Esencialmente, las clases en su aplicación entienden los mensajes que proporciona su aplicación. Esto facilita la construcción de un sistema modular en el que las cosas se pueden conectar.

En la mayoría de los lenguajes existen mecanismos (como LINQ ) para consultar cosas que cumplen con una interfaz. Esto generalmente lo ayudará a eliminar la lógica condicional porque no tendrá que decir cosas diferentes (que no son necesariamente derivadas de la misma cadena de herencia) cómo comportarse de manera similar (de acuerdo con un mensaje en particular). En su lugar, reúne todo lo que comprende un determinado mensaje (se rige por una interfaz) y publica el mensaje.

Por ejemplo, podría reemplazar ...

Me.PublishDate.Clear()
Me.Subject.Clear()
Me.Body.Clear()

...con:

For Each ctl As IClear In Me.Controls.OfType(Of IClear)()
    ctl.Clear()
Next

Que efectivamente se parece mucho a:

¡Escucha, escucha! ¡Todos los que entienden la limpieza, por favor Clearahora!

De esta manera, podemos evitar programáticamente decirle a cada cosa que se limpie. Y cuando se agregan elementos limpiables en el futuro, simplemente responden sin ningún código adicional.

Mario T. Lanza
fuente
0

El siguiente es pseudocódigo:

class MyClass{

    private MyInterface = new MyInterfaceImplementationB();

    // Code using Thingy 

}

interface MyInterface{

    myMethod();

}

class MyInterfaceImplementationA{ myMethod(){ // method implementation A } }

class MyInterfaceImplementationB{ myMethod(){ // method implementation B } }

class MyInterfaceImplementationC{ myMethod(){ // method implementation C } }

Las últimas clases pueden ser implementaciones completamente diferentes.

A menos que sea posible la herencia múltiple, la herencia impone la implementación de la clase padre haciendo las cosas más rígidas. La programación contra interfaces, por otro lado, puede permitir que su código o marco sea extremadamente flexible. Si alguna vez encuentras un caso en el que deseaste poder cambiar de clase en una cadena de herencia, entenderás por qué.

Por ejemplo, un marco que proporciona un lector originalmente destinado a leer datos del disco podría volver a implementarse para hacer algo de la misma naturaleza pero de una manera totalmente diferente. Como interpretar el código Morse, por ejemplo.

James Poulson
fuente