¿Qué significa "programar a una interfaz"?


He visto esto mencionado algunas veces y no tengo claro lo que significa. ¿Cuándo y por qué harías esto?

Sé lo que hacen las interfaces, pero el hecho de que no esté claro en esto me hace pensar que me estoy perdiendo el usarlas correctamente.

¿Es así si tuvieras que hacer:

IInterface classRef = new ObjectWhatever()

¿Podrías usar cualquier clase que implemente IInterface? ¿Cuándo necesitarías hacer eso? Lo único en lo que puedo pensar es si tienes un método y no estás seguro de qué objeto se pasará espere que se implemente IInterface. No puedo pensar con qué frecuencia tendrías que hacer eso... (Además, ¿cómo podría escribir un método que toma un objeto que implementa una interfaz? Es eso posible?)

Lo siento si perdí completamente el punto.

Author: Sameer, 2008-12-21

30 answers

Hay algunas respuestas maravillosas aquí a estas preguntas que entran en todo tipo de gran detalle sobre interfaces y código de acoplamiento flexible, inversión de control y así sucesivamente. Hay algunas discusiones bastante embriagadoras, así que me gustaría aprovechar la oportunidad para desglosar un poco las cosas para comprender por qué una interfaz es útil.

Cuando empecé a estar expuesto a las interfaces, yo también estaba confundido acerca de su relevancia. No entendía por qué los necesitabas. Si estamos usando un lenguaje como Java o C#, ya tenemos herencia y vi las interfaces como una forma de herencia más débil y pensé: "¿por qué molestarse?"En cierto sentido tenía razón, puedes pensar en las interfaces como una especie de forma débil de herencia, pero más allá de eso, finalmente entendí su uso como una construcción de lenguaje al pensar en ellas como un medio de clasificar rasgos o comportamientos comunes que exhibían potencialmente muchas clases de objetos no relacionados.

Por ejemplo say tener un juego SIM y tener las siguientes clases:

 class HouseFly inherits Insect {
   void FlyAroundYourHead(){}
   void LandOnThings(){}
 }

 class Telemarketer inherits Person {
   void CallDuringDinner(){}
   void ContinueTalkingWhenYouSayNo(){}
 }

Claramente, estos dos objetos no tienen nada en común en términos de herencia directa. Pero, se podría decir que ambos son molestos.

Digamos que nuestro juego necesita tener algún tipo de cosa al azar que molesta al jugador del juego cuando cenan. Esto podría ser un HouseFly o un Telemarketer o ambos both pero ¿cómo se permite ambos con una sola función? Y cómo se le pide a cada tipo diferente de objeto " hacer su cosa molesta " de la misma manera?

La clave para darse cuenta es que ambos Telemarketer y HouseFly comparten un comportamiento común interpretado vagamente a pesar de que no son nada iguales en términos de modelarlos. Entonces, hagamos una interfaz que ambos puedan implementar:

 interface IPest {
    void BeAnnoying();
 }

 class HouseFly inherits Insect implements IPest {
   void FlyAroundYourHead(){}
   void LandOnThings(){}

   void BeAnnoying() {
     FlyAroundYourHead();
     LandOnThings();
   }
 }

 class Telemarketer inherits Person implements IPest {
   void CallDuringDinner(){}
   void ContinueTalkingWhenYouSayNo(){}

   void BeAnnoying() {
      CallDuringDinner();
      ContinueTalkingWhenYouSayNo();
   }
 }

Ahora tenemos dos clases que pueden ser molestas a su manera. Y no necesitan derivar de la misma clase base y compartir características inherentes comunes simply simplemente necesitan satisfacer el contrato de IPest -- ese contrato es simple. Solo tienes que BeAnnoying. En este sentido, podemos modelar lo siguiente:

 class DiningRoom {

   DiningRoom(Person[] diningPeople, IPest[] pests) { ... }

   void ServeDinner() {
     when diningPeople are eating,

       foreach pest in pests
         pest.BeAnnoying();
   }
 }

Aquí tenemos un comedor que acepta un número de comensales y un número de plagas note tenga en cuenta el uso de la interfaz. Esto significa que en nuestro pequeño mundo, un miembro de la matriz pests podría ser en realidad un objeto Telemarketer o un objeto HouseFly.

El método ServeDinner se llama cuando se sirve la cena y se supone que nuestra gente en el comedor debe comer. En nuestro pequeño juego, es cuando nuestras plagas hacen su trabajo each cada plaga es instruida para ser molesta por medio de la interfaz IPest. De esta manera, podemos fácilmente tener Telemarketers y HouseFlys ser molestos en cada uno de sus propios caminos we nos importa solo que tenemos algo en el objeto DiningRoom que es una plaga, realmente no nos importa lo que es y podrían no tener nada en común con otros.

Este ejemplo de pseudo-código muy artificial (que se prolongó mucho más de lo que anticipé) está simplemente destinado a ilustrar el tipo de lo que finalmente encendió la luz para mí en términos de cuándo podríamos usar una interfaz. Me disculpo de antemano por la tontería del ejemplo, pero espero que ayude en su comprensión. Y, para estar seguros, las otras respuestas publicadas que han recibido aquí realmente cubren la gama del uso de interfaces hoy en día en patrones de diseño y metodologías de desarrollo.

 1433
Author: Peter Meyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-30 01:45:15

El ejemplo específico que solía dar a los estudiantes es que deben escribir{[15]]}

List myList = new ArrayList(); // programming to the List interface

En lugar de

ArrayList myList = new ArrayList(); // this is bad

Estos se ven exactamente iguales en un programa corto, pero si continúa usando myList 100 veces en su programa, puede comenzar a ver una diferencia. La primera declaración asegura que solo llame a los métodos en myList que están definidos por la interfaz List (así que no hay métodos específicos ArrayList). Si ha programado la interfaz de esta manera, más adelante puede decidir que realmente necesita

List myList = new TreeList();

Y solo tienes que cambiar tu código en ese punto. Ya sabes que el resto de tu código no hace nada que se rompa cambiando la implementación porque programaste a la interfaz .

Los beneficios son aún más obvios (creo) cuando se habla de parámetros de método y valores de retorno. Tome esto por ejemplo:

public ArrayList doSomething(HashMap map);

Esa declaración de método lo vincula a dos implementaciones concretas (ArrayList y HashMap). Tan pronto como ese método es llamado desde otro código, cualquier cambio a esos tipos probablemente significa que vas a tener que cambiar el código de llamada también. Sería mejor programar a las interfaces.

public List doSomething(Map map);

Ahora, no importa qué tipo de List regresar, o qué tipo de Map se pasa como parámetro. Los cambios que realice dentro del método doSomething no le obligarán a cambiar el código de llamada.

 235
Author: Bill the Lizard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-12 14:46:40

La programación en una interfaz está diciendo: "Necesito esta funcionalidad y no me importa de dónde viene."

Considere (en Java), la interfaz List versus las clases concretas ArrayList y LinkedList. Si todo lo que me importa es que tengo una estructura de datos que contiene varios elementos de datos a los que debo acceder a través de iteración, elegiría un List (y eso es el 99% del tiempo). Si sé que necesito insertar/eliminar en tiempo constante de cualquiera de los extremos de la lista, podría elegir el LinkedList concreto implementación (o más probablemente, use la interfaz Queue). Si sé que necesito acceso aleatorio por índice, elegiría la clase concreta ArrayList.

 64
Author: kdgregory,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-21 06:48:17

El uso de interfaces es un factor clave para hacer que su código sea fácilmente comprobable, además de eliminar acoplamientos innecesarios entre sus clases. Al crear una interfaz que defina las operaciones en su clase, permite que las clases que desean usar esa funcionalidad la capacidad de usarla sin depender directamente de su clase de implementación. Si más adelante decide cambiar y usar una implementación diferente, solo necesita cambiar la parte del código donde se crea la instancia de la implementación. El resto del código no necesita cambiar porque depende de la interfaz, no de la clase implementadora.

Esto es muy útil para crear pruebas unitarias. En la clase bajo prueba, depende de la interfaz e inyecta una instancia de la interfaz en la clase (o una fábrica que le permite construir instancias de la interfaz según sea necesario) a través del constructor o un settor de propiedades. La clase utiliza la interfaz proporcionada (o creada) en sus métodos. Cuando vas a escribir tus exámenes, puede simular o falsificar la interfaz y proporcionar una interfaz que responda con datos configurados en su prueba de unidad. Puede hacer esto porque su clase bajo prueba se ocupa solo de la interfaz, no de su implementación concreta. Cualquier clase que implemente la interfaz, incluyendo su clase mock o fake, servirá.

EDIT: A continuación hay un enlace a un artículo donde Erich Gamma discute su cita, " Programa a una interfaz, no aplicación."

Http://www.artima.com/lejava/articles/designprinciples.html

 35
Author: tvanfosson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-21 01:58:53

Usted debe mirar en la Inversión de Control:

En tal escenario, no escribirías esto:

IInterface classRef = new ObjectWhatever();

Escribirías algo como esto:

IInterface classRef = container.Resolve<IInterface>();

Esto entraría en una configuración basada en reglas en el objeto container, y construiría el objeto real para usted, que podría ser ObjectWhatever. Lo importante la cosa es que podrías reemplazar esta regla con algo que usara otro tipo de objeto por completo, y tu código seguiría funcionando.

Si dejamos IoC fuera de la tabla, puede escribir código que sepa que puede hablar con un objeto que hace algo específico, pero no qué tipo de objeto o cómo lo hace.

Esto sería útil al pasar parámetros.

En cuanto a su pregunta entre paréntesis " También, ¿cómo podría escribir un método que toma un objeto que implementa una Interfaz? Es eso posible?", en C# simplemente usaría el tipo de interfaz para el tipo de parámetro, así:

public void DoSomethingToAnObject(IInterface whatever) { ... }

Esto se conecta a la derecha en el "hablar con un objeto que hace algo específico."El método definido anteriormente sabe qué esperar del objeto, que implementa todo en IInterface, pero no le importa qué tipo de objeto es, solo que se adhiere al contrato, que es lo que es una interfaz.

Por ejemplo, probablemente estés familiarizado con calculadoras y probablemente han utilizado bastantes en sus días, pero la mayoría de las veces son todos diferentes. Usted, por otro lado, sabe cómo debe funcionar una calculadora estándar, por lo que puede usarlas todas, incluso si no puede usar las características específicas que tiene cada calculadora que ninguna de las otras tiene.

Esta es la belleza de las interfaces. Puede escribir un fragmento de código, que sabe que obtendrá objetos pasados a él que puede esperar cierto comportamiento de. No le importa uno hoot qué tipo de objeto es, solo que apoya el comportamiento necesario.

Permítanme darles un ejemplo concreto.

Tenemos un sistema de traducción personalizado para formularios de Windows. Este sistema recorre los controles de un formulario y traduce el texto en cada uno. El sistema sabe cómo manejar controles básicos, como el tipo de control que tiene una propiedad de Texto, y cosas básicas similares, pero para cualquier cosa básica, se queda corto.

Ahora, dado que los controles heredan de clases predefinidas que no tenemos control sobre, podríamos hacer una de tres cosas:

  1. Crear soporte para nuestro sistema de traducción para detectar específicamente con qué tipo de control está trabajando y traducir los bits correctos (pesadilla de mantenimiento)
  2. Build support into base classes (imposible, ya que todos los controles heredan de diferentes clases predefinidas)
  3. Añadir soporte de interfaz

Así lo hicimos nr. 3. Todos nuestros controles implementan ILocalizable, que es una interfaz que nos da un método, la capacidad de traducir "a sí mismo" en un contenedor de texto/reglas de traducción. Como tal, el formulario no necesita saber qué tipo de control ha encontrado, solo que implementa la interfaz específica, y sabe que hay un método al que puede llamar para localizar el control.

 34
Author: Lasse Vågsæther Karlsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-15 02:03:05

La programación en una interfaz no tiene absolutamente nada que ver con interfaces abstractas como vemos en Java o .NET. Ni siquiera es un concepto de OOP.

Lo que realmente significa es no jugar con las partes internas de un objeto o estructura de datos. Utilice la interfaz del programa Abstracto, o API, para interactuar con sus datos. En Java o C# eso significa usar propiedades y métodos públicos en lugar de acceso a campos sin procesar. Para C eso significa usar funciones en lugar de punteros raw.

EDITAR: Y con las bases de datos significa usar vistas y procedimientos almacenados en lugar de acceso directo a la tabla.

 28
Author: Jonathan Allen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-19 20:06:39

Código a la Interfaz No la Implementación no tiene NADA que ver con Java, ni su construcción de interfaz.

Este concepto fue llevado a la prominencia en los libros de Patterns / Gang of Four, pero lo más probable es que existiera mucho antes de eso. El concepto ciertamente existió mucho antes de que Java existiera.

La construcción de la interfaz Java fue creada para ayudar en esta idea (entre otras cosas), y la gente se ha centrado demasiado en la construcción como el centro de la significado en lugar de la intención original. Sin embargo, es la razón por la que tenemos métodos y atributos públicos y privados en Java, C++, C#, etc.

Significa simplemente interactuar con la interfaz pública de un objeto o sistema. No te preocupes o incluso anticipar cómo hace lo que hace internamente. No se preocupe por cómo se implementa. En código orientado a objetos, es por eso que tenemos métodos/atributos públicos vs.privados. Estamos destinados a utilizar los métodos públicos porque los métodos privados están allí solo para usar internamente, dentro de la clase. Constituyen la implementación de la clase y se pueden cambiar según sea necesario sin cambiar la interfaz pública. Supongamos que con respecto a la funcionalidad, un método en una clase realizará la misma operación con el mismo resultado esperado cada vez que lo llame con los mismos parámetros. Permite al autor cambiar cómo funciona la clase, su implementación, sin romper la forma en que la gente interactúa con ella.

Y se puede programar a la interfaz, no el implementación sin usar una construcción de interfaz. Puede programar en la interfaz no la implementación en C++, que no tiene una construcción de interfaz. Puede integrar dos sistemas empresariales masivos de forma mucho más robusta, siempre y cuando interactúen a través de interfaces públicas (contratos) en lugar de llamar a métodos en objetos internos de los sistemas. Se espera que las interfaces reaccionen siempre de la misma manera esperada dados los mismos parámetros de entrada; si se implementan en la interfaz y no la implementación. El concepto funciona en muchos lugares.

Agite la idea de que las Interfaces Java tienen algo que ver con el concepto de 'Programa a la Interfaz, no a la Implementación'. Pueden ayudar a aplicar el concepto, pero son no el concepto.

 21
Author: Bill Rosmus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-21 21:21:22

Parece que entiendes cómo funcionan las interfaces, pero no estás seguro de cuándo usarlas y qué ventajas ofrecen. Aquí hay algunos ejemplos de cuándo una interfaz tendría sentido:

// if I want to add search capabilities to my application and support multiple search
// engines such as google, yahoo, live, etc.

interface ISearchProvider
{
    string Search(string keywords);
}

Entonces podría crear GoogleSearchProvider, YahooSearchProvider, LiveSearchProvider, etc.

// if I want to support multiple downloads using different protocols
// HTTP, HTTPS, FTP, FTPS, etc.
interface IUrlDownload
{
    void Download(string url)
}

// how about an image loader for different kinds of images JPG, GIF, PNG, etc.
interface IImageLoader
{
    Bitmap LoadImage(string filename)
}

Luego crea JpegImageLoader, GifImageLoader, PngImageLoader, etc.

La mayoría de los sistemas de complementos y complementos funcionan fuera de las interfaces.

Otro uso popular es para el Repositorio patrón. Digamos que quiero cargar una lista de códigos postales de diferentes fuentes

interface IZipCodeRepository
{
    IList<ZipCode> GetZipCodes(string state);
}

Entonces podría crear un XMLZipCodeRepository, SQLZipCodeRepository, CSVZipCodeRepository, etc. Para mis aplicaciones web a menudo creo repositorios XML desde el principio para que pueda poner algo en marcha antes de que la base de datos Sql esté lista. Una vez que la base de datos está lista escribo un SQLRepository para reemplazar la versión XML. El resto de mi código permanece sin cambios ya que ejecuta soley fuera de interfaz.

Los métodos pueden aceptar interfaces tales como:

PrintZipCodes(IZipCodeRepository zipCodeRepository, string state)
{
    foreach (ZipCode zipCode in zipCodeRepository.GetZipCodes(state))
    {
        Console.WriteLine(zipCode.ToString());
    }
}
 12
Author: Todd Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-21 04:50:48

Hace que su código sea mucho más extensible y más fácil de mantener cuando tiene conjuntos de clases similares. Soy un programador junior, así que no soy un experto, pero acabo de terminar un proyecto que requería algo similar.

Trabajo en software del lado del cliente que habla con un servidor que ejecuta un dispositivo médico. Estamos desarrollando una nueva versión de este dispositivo que tiene algunos componentes nuevos que el cliente debe configurar en ocasiones. Hay dos tipos de componentes nuevos, y son diferentes, pero también son muy similares. Básicamente, tuve que crear dos formularios de configuración, dos clases de listas, dos de todo.

Decidí que sería mejor crear una clase base abstracta para cada tipo de control que contuviera casi toda la lógica real, y luego tipos derivados para cuidar las diferencias entre los dos componentes. Sin embargo, las clases base no habrían sido capaces de realizar operaciones en estos componentes si tuviera que preocuparme por los tipos todo el tiempo (bueno, podrían tener, pero habría habido una declaración " si " o cambiar en cada método).

Definí una interfaz simple para estos componentes y todas las clases base hablan con esta interfaz. Ahora, cuando cambio algo, prácticamente 'solo funciona' en todas partes y no tengo duplicación de código.

 10
Author: Ed S.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-21 01:07:05

Si programa en Java, JDBC es un buen ejemplo. JDBC define un conjunto de interfaces pero no dice nada sobre la implementación. Sus aplicaciones se pueden escribir contra este conjunto de interfaces. En teoría, usted elige algún controlador JDBC y su aplicación simplemente funcionaría. Si descubre que hay un controlador JDBC más rápido o "mejor" o más barato o por cualquier razón, puede volver a configurar su archivo de propiedad, y sin tener que hacer ningún cambio en su aplicación, su la aplicación seguiría funcionando.

 8
Author: Kevin Le - Khnle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-21 01:20:57

La programación para interfaces es impresionante, promueve el acoplamiento suelto. Como mencionó @lassevk, la inversión del control es un gran uso de esto.

Además, busque en SOLID principals . aquí hay una serie de videos

Pasa por un código duro (ejemplo fuertemente acoplado) luego mira las interfaces, finalmente progresando a una herramienta IoC/DI (NInject)

 8
Author: dbones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-30 13:03:26

Además de la respuesta ya seleccionada (y las diversas publicaciones informativas aquí), recomiendo encarecidamente tomar una copia de Head First Design Patterns. Es una lectura muy fácil y responderá su pregunta directamente, explicará por qué es importante y le mostrará muchos patrones de programación que puede usar para hacer uso de ese principio (y otros).

 6
Author: whaley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-08 21:32:05

Hay mucha explicación, pero para hacerlo aún más simple. Tomemos por ejemplo un List. Se puede implementar una lista con as:

  1. una matriz interna
  2. Una lista vinculada
  3. otras medidas de aplicación

Al construir una interfaz, digamos un List. Solo codifica en cuanto a la definición de Lista o lo que List significa en realidad.

Puede usar cualquier tipo de implementación internamente, por ejemplo, una implementación array. Pero supongamos que desea cambiar la implementación por alguna razón decir un error o rendimiento. Entonces solo tienes que cambiar la declaración List<String> ls = new ArrayList<String>() a List<String> ls = new LinkedList<String>().

En ningún otro lugar en el código, tendrá que cambiar nada más; Porque todo lo demás se construyó sobre la definición de List.

 6
Author: Jatin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-09 06:46:33

Llego tarde a esta pregunta, pero quiero mencionar aquí que la línea "Programa para una interfaz, no una implementación" tuvo una buena discusión en el libro de Patrones de diseño de GoF (Gang of Four).

Declaró, en la p. 18:

Programa a una interfaz, no una implementación

No declare variables como instancias de clases concretas particulares. En su lugar, commit solo a una interfaz definida por una clase abstracta. Usted encontrará que esto es un tema común de los patrones de diseño en este libro.

Y por encima de eso, comenzó con:

Manipular objetos solo en términos de la interfaz definida por clases abstractas tiene dos beneficios:

  1. Los clientes no son conscientes de los tipos específicos de objetos que utilizan, siempre y cuando los objetos se adhieran a la interfaz que los clientes esperan.
  2. Los clientes no conocen las clases que implementan estos objetos. Los clientes solo conocen el clase(es) abstracta (s) definiendo la interfaz.

Así que en otras palabras, no escriban sus clases para que tenga un método quack() para patos, y luego un método bark() para perros, porque son demasiado específicos para una implementación particular de una clase (o subclase). En su lugar, escriba el método utilizando nombres que sean lo suficientemente generales como para ser utilizados en la clase base, como giveSound() o move(), para que puedan ser utilizados para patos, perros o incluso coches, y luego el cliente de sus clases puede simplemente diga .giveSound() en lugar de pensar si usar quack() o bark() o incluso determinar el tipo antes de emitir el mensaje correcto para ser enviado al objeto.

 6
Author: 太極者無極而生,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-07 04:11:31

Para agregar a las publicaciones existentes, a veces la codificación a interfaces ayuda en proyectos grandes cuando los desarrolladores trabajan en componentes separados simultáneamente. Todo lo que necesita es definir las interfaces por adelantado y escribir código en ellas mientras que otros desarrolladores escriben código en la interfaz que está implementando.

 4
Author: edgi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-21 01:08:55

También es bueno para Pruebas unitarias, puede inyectar sus propias clases (que cumplan con los requisitos de la interfaz) en una clase que depende de ella

 4
Author: Richard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-08 21:12:54

Así que, solo para hacer esto bien, la ventaja de una interfaz es que puedo separar la llamada de un método de cualquier clase en particular. En lugar de crear una instancia de la interfaz, donde la implementación se da de cualquier clase que elija que implementa esa interfaz. Lo que me permite tener muchas clases, que tienen una funcionalidad similar pero ligeramente diferente y en algunos casos (los casos relacionados con la intención de la interfaz) no importa qué objeto es.

Para por ejemplo, podría tener una interfaz de movimiento. Un método que hace que algo 'se mueva' y cualquier objeto (Persona, Automóvil, Gato) que implemente la interfaz de movimiento podría pasarse y decirle que se mueva. Sin el método cada sabiendo el tipo de clase que es.

 3
Author: Damien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-21 22:05:50

Imagine que tiene un producto llamado 'Zebra' que puede ser extendido por plugins. Encuentra los plugins mediante la búsqueda de archivos DLL en algún directorio. Carga todos esos archivos DLL y usa la reflexión para encontrar cualquier clase que implemente IZebraPlugin, y luego llama a los métodos de esa interfaz para comunicarse con los plugins.

Esto lo hace completamente independiente de cualquier clase de plugin específica-no le importa cuáles son las clases. Solo le importa que cumplan con la especificación de la interfaz.

Las interfaces son una forma de definir puntos de extensibilidad como esta. El código que habla a una interfaz está más vagamente acoplado - de hecho no está acoplado en absoluto a ningún otro código específico. Puede interactuar con plugins escritos años más tarde por personas que nunca han conocido al desarrollador original.

En su lugar, podría usar una clase base con funciones virtuales - todos los complementos se derivarían de la clase base. Pero esto es mucho más limitante porque una clase solo puede tener una base clase, mientras que puede implementar cualquier número de interfaces.

 3
Author: Daniel Earwicker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-27 14:15:25

Explicación de C++.

Piense en una interfaz como sus métodos públicos de clases.

Entonces podría crear una plantilla que 'dependa' de estos métodos públicos para llevar a cabo su propia función (hace llamadas a funciones definidas en la interfaz pública de clases). Digamos que esta plantilla es un contenedor, como una clase Vectorial, y la interfaz de la que depende es un algoritmo de búsqueda.

Cualquier clase de algoritmo que define el Vector de funciones/interfaz al que hace llamadas satisfará el "contrato" (como alguien explicó en la respuesta original). Los algoritmos ni siquiera necesitan ser de la misma clase base; el único requisito es que las funciones/métodos de los que depende el Vector (interfaz) estén definidos en su algoritmo.

El punto de todo esto es que usted podría suministrar cualquier algoritmo/clase de búsqueda diferente, siempre y cuando suministrara la interfaz de la que depende el Vector (búsqueda de burbujas, búsqueda secuencial, búsqueda rápida).

Es posible que también desee diseñar otros contenedores (listas, colas) que aprovecharían el mismo algoritmo de búsqueda que Vector haciendo que cumplan con la interfaz/contrato de la que dependen sus algoritmos de búsqueda.

Esto ahorra tiempo (principio OOP 'reutilización de código') ya que puede escribir un algoritmo una vez en lugar de una y otra vez y otra vez específico para cada nuevo objeto que cree sin complicar demasiado el problema con un árbol de herencia demasiado grande.

En cuanto a 'perderse' en cómo funcionan las cosas; a lo grande (al menos en C++), ya que así es como funciona la mayor parte del framework de la Biblioteca de PLANTILLAS Estándar.

Por supuesto, cuando se utilizan clases de herencia y abstractas, la metodología de programación a una interfaz cambia; pero el principio es el mismo, sus funciones/métodos públicos son su interfaz de clases.

Este es un gran tema y uno de los principios fundamentales de los Patrones de Diseño.

 3
Author: Trae Barlow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-18 22:52:53

En Java todas estas clases concretas implementan la interfaz CharSequence:

CharBuffer, String, StringBuffer, StringBuilder

Estas clases concretas no tienen una clase padre común que no sea Objeto, por lo que no hay nada que las relacione, aparte del hecho de que cada una tiene algo que ver con matrices de caracteres, representando tales, o manipulando tales. Por ejemplo, los caracteres de String no se pueden cambiar una vez que se crea una instancia de un objeto String, mientras que los caracteres de StringBuffer o StringBuilder se pueden editar.

Sin embargo, cada una de estas clases es capaz de implementar adecuadamente los métodos de interfaz CharSequence:

char charAt(int index)
int length()
CharSequence subSequence(int start, int end)
String toString()

En algunos casos las clases de Java class library que solían aceptar String han sido revisadas para aceptar ahora la interfaz CharSequence. Por lo tanto, si tiene una instancia de StringBuilder, en lugar de extraer un objeto de cadena (lo que significa crear una instancia de un nuevo objeto), puede pasar StringBuilder ya que implementa la interfaz CharSequence.

La interfaz anexable que implementan algunas clases tiene el mismo tipo de beneficio para cualquier situación en la que se pueden agregar caracteres a una instancia de la instancia de objeto de clase concreta subyacente. Todas estas clases concretas implementan la interfaz anexable:

BufferedWriter, CharArrayWriter, CharBuffer, FileWriter, FilterWriter, LogStream, OutputStreamWriter, PipedWriter, PrintStream, PrintWriter, StringBuffer, StringBuilder, [2] [2]]}

 2
Author: RogerV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-21 04:17:54

En términos simples... Si estoy escribiendo una nueva clase Swimmer para añadir la funcionalidad swim () y necesito usar un objeto de clase Dog, y esta clase Dog implementa la interfaz Animal que declara swim () [Para entender mejor...usted puede dibujar un diagrama en cuanto a lo que estoy hablando]. En la parte superior de la jerarquía(Animal) es muy abstracto, mientras que en la parte inferior (Perro) es muy concreto. La forma en que pienso en "programación para interfaces" es que, mientras escribo la clase de nadador, quiero escribir mi código contra la interfaz que está tan lejos de esa jerarquía que en este caso es Animal object. Una interfaz está libre de detalles de implementación y por lo tanto hace que su código se acople libremente. Los detalles de la implementación se pueden cambiar con el tiempo, sin embargo, no afectaría al código restante ya que todo lo que está interactuando es con la interfaz y no con la implementación. No te importa cómo es la implementación...todo lo que sabes es que habrá una clase que implementaría la interfaz.

 2
Author: Abhishek Shrivastava,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-28 16:44:22

Cuento corto:Cartero se le pide que vaya a casa por casa y recibir las cubiertas contiene (cartas,documentos,cheques,tarjeta de regalo,solicitud,loveletter) con la dirección escrita en ella para entregar.

Supongamos que no hay cobertura y pedirle al cartero que vaya a casa por casa y reciba todas las cosas y entregue a otra persona que el cartero pueda confundirse,{[17]]}

Así que mejor envolverlo con cubierta (en nuestra historia es interfaz) entonces él hará su trabajo bien.

Ahora cartero trabajo es recibir y entrega las cubiertas solamente..(no se molestó en lo que hay dentro de la portada).

Crear tipo de interface no tipo real, pero implementar con tipo real.

Crear a la interfaz significa que sus componentes consiguen Encaja fácilmente en el resto del código

Les doy ejemplo.

Tiene la interfaz de avión como se muestra a continuación.

interface Airplane{
    parkPlane();
    servicePlane();
}

Supongamos que tiene métodos en su clase Controlador de Planos como

parkPlane(Airplane plane)

Y

servicePlane(Airplane plane)

Implementado en su programa. No ROMPERÁ su código. Quiero decir, no necesita cambiar mientras acepte argumentos como AirPlane.

Porque aceptará cualquier avión a pesar del tipo real, flyer, highflyr, fighter, etc.

También, en una colección:

List<Airplane> plane; // Tomará todos sus aviones.

El siguiente ejemplo aclarará su comprensión.


Tienes un avión de combate que lo implementa, así que{[17]]}

public class Fighter implements Airplane {

    public void  parkPlane(){
        // Specific implementations for fighter plane to park
    }
    public void  servicePlane(){
        // Specific implementatoins for fighter plane to service.
    }
}

Lo mismo para HighFlyer y otras clases:

public class HighFlyer implements Airplane {

    public void  parkPlane(){
        // Specific implementations for HighFlyer plane to park
    }

    public void  servicePlane(){
        // specific implementatoins for HighFlyer plane to service.
    }
}

Ahora piensa que tus clases de controladores usan AirPlane varias veces,

Supongamos que su clase Controller es ControlPlane como abajo,

public Class ControlPlane{ 
 AirPlane plane;
 // so much method with AirPlane reference are used here...
}

Aquí la magia viene como

Puede hacer que sus nuevas AirPlane instancias de tipo tantas como desee y no está cambiando

Código de la clase ControlPlane.

Puede agregar instancia..

JumboJetPlane // implementing AirPlane interface.
AirBus        // implementing AirPlane interface.

Puede eliminar instancias.. de tipos creados previamente también.

 2
Author: Sanjay Rabari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-08 10:42:54

P: -... "Usted podría utilizar cualquier clase que implementa la interfaz?"
R: - Sí.

P: -... "¿Cuándo necesitarías hacer eso?"
R: - Cada vez que necesite una clase(s) que implementa la interfaz(s).

Nota: no pudimos instanciar una interfaz no implementada por una clase - Cierto.

  • ¿por qué?
  • porque la interfaz solo tiene prototipos de métodos, no definiciones (solo nombres de funciones, no su lógica)

AnIntf anInst = new Aclass ();
// podríamos hacer esto solo si Aclass implementa AnIntf.
// anInst tendrá referencia Aclass.


Nota:
Ahora podríamos entender lo que sucede si Bclass y Cclass implementan el mismo Dintf.

Dintf bInst = new Bclass();  
// now we could call all Dintf functions implemented (defined) in Bclass.

Dintf cInst = new Cclass();  
// now we could call all Dintf functions implemented (defined) in Cclass.

Lo que tenemos:
mismos prototipos de interfaz (nombres de funciones en la interfaz), y llamar a diferentes aplicación.

Bibliografía:
Prototipos - wikipedia

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-09 06:53:31

Interface es como contract donde desea que su clase de implementación implemente métodos escritos en contract(Interface).Dado que Java no proporciona herencia múltiple,la programación en la interfaz es una buena manera de lograr el propósito de la herencia múltiple.Si tiene una clase A que ya está extendiendo alguna otra clase B, pero desea que la clase A también siga ciertas pautas o implemente cierto contrato, entonces puede hacerlo programando la estrategia de interfaz.

 1
Author: Shivam Sugandhi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-27 10:44:19

Puede ser ventajoso programar a interfaces, incluso cuando no dependemos de abstracciones.

Programar para interfaces nos obliga a usar un subconjunto contextualmente apropiado de un objeto. Eso ayuda porque: {[32]]}

  1. nos impide hacer cosas contextualmente inapropiadas, y {[39]]}
  2. nos permite cambiar la implementación de forma segura en el futuro.

Por ejemplo, considere una clase Person que implementa el Friend y el Employee interfaz.

class Person implements AbstractEmployee, AbstractFriend {

}

En el contexto del cumpleaños de la persona, programamos a la interfaz Friend, para evitar tratar a la persona como un Employee.

function party() {
    const friend: Friend = new Person("Kathryn");
    friend.HaveFun();
}

En el contexto del trabajo de la persona, programamos a la interfaz Employee, para evitar difuminar los límites del lugar de trabajo.

function workplace() {
    const employee: Employee = new Person("Kathryn");
    employee.DoWork();
}

Genial. Nos hemos comportado apropiadamente en diferentes contextos, y nuestro software está funcionando bien.

En el futuro, si nuestro negocio cambia para trabajar con perros, podemos cambiar la software con bastante facilidad. Primero, creamos la clase Dog que implementa tanto Friend como Employee. Entonces, cambiamos con seguridad new Person() a new Dog(). Incluso si ambas funciones tienen miles de líneas de código, esa simple edición funcionará porque sabemos que lo siguiente es cierto:

  1. La función party utiliza solo el subconjunto Friend de Person.
  2. La función workplace utiliza solo el subconjunto Employee de Person.
  3. Class Dog implementa las interfaces Friend y Employee.

Sobre la de otro lado, si bien party o workplace se han programado contra Person, habría un riesgo de tener Person código específico. Cambiar de Person a Dog requeriría que revisemos el código para extirpar cualquier código específico de Person que Dog no admita.

La moraleja : programar para interfaces ayuda a nuestro código a comportarse apropiadamente y a estar listo para el cambio. También prepara nuestro código para depender de abstracciones, lo que trae aún más ventajas.

 1
Author: Shaun Luttin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-03 21:10:38

También veo muchas respuestas buenas y explicativas aquí, así que quiero dar mi punto de vista aquí, incluyendo algo de información adicional que noté al usar este método.

Pruebas unitarias

Durante los últimos dos años, he escrito un proyecto de hobby y no escribí pruebas unitarias para él. Después de escribir unas 50K líneas descubrí que sería realmente necesario escribir pruebas unitarias. No usé interfaces (o muy escasamente) ... y cuando hice mi primera prueba unitaria, encontré era complicado. ¿Por qué?

Porque tuve que hacer muchas instancias de clase, usadas para la entrada como variables de clase y/o parámetros. Por lo tanto, las pruebas se parecen más a las pruebas de integración (tener que hacer un 'marco' completo de clases ya que todo estaba unido).

Miedo a las interfaces Así que decidí usar interfaces. Mi miedo era que tenía que implementar todas las funcionalidades en todas partes (en todas las clases usadas) varias veces. De alguna manera esto es cierto, sin embargo, mediante el uso de la herencia se puede reducir mucho.

Combinación de interfaces y herencia Descubrí que la combinación es muy buena para ser utilizada. Doy un ejemplo muy simple.

public interface IPricable
{
    int Price { get; }
}

public interface ICar : IPricable

public abstract class Article
{
    public int Price { get { return ... } }
}

public class Car : Article, ICar
{
    // Price does not need to be defined here
}

De esta manera no es necesario copiar código, sin dejar de tener el beneficio de usar un coche como interfaz (ICar).

 0
Author: Michel Keijzers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-18 13:23:31

Comencemos con algunas definiciones primero:

Interfaz n. El conjunto de todas las firmas definidas por las operaciones de un objeto se denomina interfaz al objeto

Tipo n. Una interfaz particular

Un ejemplo simple de una interfaz como se define anteriormente sería todos los métodos de objeto PDO como query(), commit(), close() etc., como un todo, no por separado. Estos métodos, es decir, su interfaz definir el conjunto completo de mensajes, solicitudes que se pueden enviar al objeto.

A type como se define anteriormente es una interfaz particular. Usaré la interfaz de forma inventada para demostrar: draw(), getArea(), getPerimeter() etc..

Si un objeto es del tipo de base de datos queremos decir que acepta mensajes / solicitudes de la interfaz de la base de datos, query(), commit() etc.. Los objetos pueden ser de muchos tipos. Puede hacer que un objeto de base de datos sea del tipo shape siempre y cuando implemente su interfaz, en cuyo caso sería subescritura.

Muchos objetos pueden ser de muchas interfaces/tipos diferentes e implementar esa interfaz de manera diferente. Esto nos permite sustituir objetos, permitiéndonos elegir cuál usar. También conocido como polimorfismo.

El cliente solo conocerá la interfaz y no la implementación.

Así que en esencia programar una interfaz implicaría hacer algún tipo de clase abstracta como Shape con el interfaz especificada solamente i. e.draw(), getCoordinates(), getArea() etc.. Y luego tienen diferentes clases concretas implementar esas interfaces como una clase de Círculo, clase Cuadrada, clase Triángulo. Por lo tanto programa a una interfaz no una implementación.

 0
Author: Robert Rocha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-05 23:48:47

Programa a una interfaz permite cambiar la implementación del contrato definido por la interfaz sin problemas. Permite un acoplamiento flexible entre el contrato y las implementaciones específicas.

IInterface classRef = new ObjectWhatever()

¿Podría usar cualquier clase que implemente IInterface? ¿Cuándo necesitarías hacer eso?

Echa un vistazo a esta pregunta SE para un buen ejemplo.

¿Por qué debería preferirse la interfaz para una clase Java?

Utiliza un Interfaz hit rendimiento?

Si es así, ¿cuánto?

Sí. Tendrá una ligera sobrecarga de rendimiento en menos de segundos. Pero si su aplicación tiene el requisito de cambiar la implementación de la interfaz dinámicamente, no se preocupe por el impacto en el rendimiento.

¿Cómo puedes evitarlo sin tener que mantener dos bits de código?

No intente evitar múltiples implementaciones de interfaz si su aplicación las necesita. En ausencia de acoplamiento de interfaz con una implementación específica, es posible que tenga que implementar el parche para cambiar una implementación a otra implementación.

Un buen caso de uso: Implementación del patrón de Estrategia:

Ejemplo del Mundo Real del Patrón de Estrategia

 0
Author: Ravindra babu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-25 13:31:33

No retengo interface s son lo más importante en un lenguaje: se usa más comúnmente la clase heredar. Pero de todos modos son importantes!
Por ejemplo (esto es Java código, pero simplemente se puede adaptar a C# o muchos otros idiomas):

interface Convertable<T> {

    T convert();
}

public class NumerableText implements Convertable<Integer> {

    private String text = "";

    public NumerableText() { }

    public NumerableText(String text) {
        this.text = text;
    }

    public String getText() {
        return this.text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public Integer convert() {
        return this.text.hashCode();
    }
}

public class NumerableTextArray implements Convertable<Integer> {

    private String[] textArray = "";

    public NumerableTextArray() { }

    public NumerableTextArray(String[] textArray) {
        this.textArray = textArray;
    }

    public String[] getTextArray() {
        return this.textArray;
    }

    public void setTextArray(String[] text) {
        this.textArray = textArray;
    }

    public Integer convert() {
        Integer value = 0;
        for (String text : textArray)
            value += text.hashCode();
        return value;
    }
}

public class Foo {

    public static void main() {
        Convertable<Integer> num1 = new NumerableText("hello");
        Convertable<Integer> num2 = new NumerableTextArray(new String[] { "test n°1", "test n°2" });
        System.out.println(String.valueOf(num1.convert()));
        System.out.println(String.valueOf(num2.convert()));
        //Here are you two numbers generated from two classes of different type, but both with the method convert(), which allows you to get that number.
    }
}
 0
Author: Davide Cannizzo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-04 14:55:57

El programa para la interfaz significa que no proporcione códigos duros de la manera correcta, significa que sus códigos deben extenderse sin romper la funcionalidad anterior..... solo extensiones que no editan los códigos anteriores

 0
Author: ndoty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-30 15:55:21