2010-01-02 10 views
32

Duplicar posible:
What does it mean to “program to an interface”?"Programa a una interfaz". Qué significa eso?

que siguen llegando a través de este término:

Programa

a una interfaz.

¿Qué significa exactamente? Un escenario de diseño de la vida real sería muy apreciado.

+1

otro duplicado. Me gusta esta pregunta realmente, pero ha sido publicada muchas, muchas veces ... ¿Intentó usar la barra de búsqueda? aquí encontrará muchas sugerencias: http://stackoverflow.com/search?q=programming+to+interface –

Respuesta

65

En pocas palabras, en lugar de escribir sus clases de una manera que dice

dependo de esta clase específica para hacer mi trabajo

lo escribe de una manera que dice

dependo de cualquier clase que hace esto para hacer mi trabajo.

El primer ejemplo representa una clase que depende de una implementación concreta concreta para hacer su trabajo. Inherentemente, eso no es muy flexible.

El segundo ejemplo representa una clase escrita en una interfaz . No le importa qué objeto concreto use, solo le preocupa que implemente cierto comportamiento. Esto hace que la clase sea mucho más flexible, ya que se puede proporcionar con cualquier cantidad de implementaciones concretas para hacer su trabajo.

Como ejemplo, una clase particular puede necesitar realizar un poco de registro. Si escribe la clase para que dependa de un TextFileLogger, la clase se verá forzada a escribir sus registros en un archivo de texto. Si desea cambiar el comportamiento del registro, debe cambiar la clase en sí. La clase está estrechamente unida con su registrador.

Sin embargo, si escribe la clase para que dependa de una interfaz ILogger, y luego proporciona a la clase un TextFileLogger, habrá logrado lo mismo, pero con el beneficio adicional de ser mucho más flexible. Puede proporcionar cualquier otro tipo de ILogger a voluntad, sin cambiar la clase. La clase y su registrador ahora están débilmente acoplados, y su clase es mucho más flexible.

+3

Simple. Preciso. –

+0

Desafortunadamente, no es una buena respuesta. "Programa * a * una interfaz" significa * solo * eso. No significa que no puede depender de una clase específica para hacer el trabajo. Como un contraejemplo a su ejemplo 'ILogger', ofrezco para consideración las clases' java.util.logging.Logger' y 'org.apache.log4j.Logger': estas dos populares API de registro * no * implementan una interfaz separada, que se usa directamente desde el código del cliente. Código de cliente que todavía está "programando para la interfaz", la interfaz de la clase 'Logger'. –

+1

@ Rogério El punto no es si una determinada clase de Java proporciona una interfaz explícita, sino si el código que se escribe depende de la clase específica en lugar de la interfaz que expone. Si escribe código que depende específicamente de 'org.apache.log4j.Logger', '_ no está_' 'programando en una interfaz' '. Si escribe código que no le importa si el registrador proporcionado es 'java.util.logging.Logger' o' org.apache.log4j.Logger' o cualquier otra implementación del registrador que expone la interfaz común, entonces _are_ programación a un interfaz. –

2

"Programación de una interfaz" ocurre cuando usa bibliotecas, otro código que depende sobre en tu propio código. Entonces, la forma en que otro código se representa para usted, los nombres de los métodos, sus parámetros, valores de retorno, etc. constituyen la interfaz que debe programar. Entonces se trata de cómo usar código de terceros.

También significa, que usted no tiene que preocuparse por la parte interna de la que depende el código, siempre y cuando la interfaz sigue siendo el mismo, su código es seguro (bueno, más o menos ...)

Técnicamente hay detalles más finos, como conceptos de lenguaje llamados "interfaces" en Java, por ejemplo.

Si desea obtener más información, se puede pedir lo que "La implementación de una interfaz" significa ...

7

Ejemplos del mundo real son applenty. Uno de ellos:

Para JDBC, está utilizando la interfaz java.sql.Connection. Sin embargo, cada controlador JDBC proporciona su propia implementación de Connection. No es necesario que sepa nada sobre la implementación particular, porque corresponde a en la interfaz Connection.

Otra es del marco de colecciones de Java. Hay una interfaz java.util.Collection, que define los métodos size, add y remove (entre muchos otros). Por lo tanto, puede usar todos los tipos de colecciones indistintamente. Supongamos que tiene lo siguiente:

public float calculateCoefficient(Collection collection) { 
    return collection.size() * something/somethingElse; 
} 

Y otros dos métodos que invocan este. Uno de los otros métodos usa un LinkedList porque es más eficiente para sus propósitos, y el otro usa un TreeSet.

Dado que tanto LinkedList como TreeSet implementan la interfaz Collection, puede usar solo un método para realizar el cálculo del coeficiente. No es necesario duplicar tu código.

Y aquí viene el "programa para una interfaz": no importa cómo se implemente exactamente el método size(), usted sabe que debe devolver el tamaño de la colección, es decir,ha programado en la interfaz Collection, en lugar de a LinkedList y TreeSet en particular.

Pero mi consejo es encontrar una lectura, tal vez un libro ("Pensando en Java", por ejemplo), donde se explica el concepto en detalle.

4

Cada objeto tiene una interfaz expuesta. Una colección tiene Add, Remove, At, etc. Una toma puede tener Send, Receive, Close y así sucesivamente.

Todos los objetos a los que se puede hacer referencia tienen una implementación concreta de estas interfaces.

Ambas cosas son obvias, sin embargo lo que es algo menos obvio ...

El código no debe depender de los detalles de implementación de un objeto, sólo su interfaz publicada.

Si lo lleva al extremo, solo codificaría contra Collection<T> y así sucesivamente (en lugar de ArrayList<T>). Más prácticamente, solo asegúrate de cambiar algo conceptualmente idéntico sin romper tu código.

Para elaborar el ejemplo Collection<T>: usted tiene una colección de algo, en realidad se está utilizando ArrayList<T> porque por qué no. Debe asegurarse de que su código no se vaya a romper si, por ejemplo, termina usando LinkedList<T> en el futuro.

+0

"Cada objeto tiene una interfaz expuesta" - um. No, no? Los que mencionaste lo hacen, pero muchos no implementan ninguna interfaz. – Nyerguds

2

Básicamente significa que la única parte de la biblioteca que va a usar debe confiar en que es su API (interfaz de programación de aplicaciones) y que no debe basar su aplicación en la implementación concreta de la biblioteca.

por ejemplo. Supone que tienes una biblioteca que te da un stack. La clase te da un par de métodos. Digamos push, pop, isempty y top. Debe escribir su aplicación confiando solo en esto. Una forma de violar esto sería echar un vistazo al interior y descubrir que la pila se implementa utilizando una matriz de algún tipo, de modo que si extrae de una pila vacía, obtendría algún tipo de excepción de índice y luego captaría esto en lugar de confiar en el método isempty que proporciona la clase. El primer enfoque fallaría si el proveedor de la biblioteca pasara de usar una matriz a usar algún tipo de lista, mientras que la última seguiría funcionando suponiendo que el proveedor mantuviera su API funcionando.

8

El polimorfismo depende de la programación en una interfaz, no en una implementación.

Hay dos beneficios para la manipulación de objetos únicamente en términos de la interfaz definida por las clases abstractas:

  1. clientes no están al tanto de los tipos específicos de objetos que utilizan, siempre que los objetos se adhieren a la interfaz que los clientes esperan.
  2. Los clientes no son conscientes de las clases que implementan estos objetos. Los clientes solo conocen la (s) clase (s) abstracta (s) que definen la interfaz.

Esto reduce enormemente las dependencias de implementación entre los subsistemas que conduce a este principio de programación en una interfaz.

Consulte el Factory Method pattern para un mayor razonamiento de este diseño.

Fuente: "Design Patterns: Elements of Reusable Object-Oriented Software" de G.O.F.

Ver también: Factory Pattern. When to use factory methods?

18

Una interfaz es una colección de métodos relacionados, que solo contiene las firmas de esos métodos, no la implementación real.
Si una clase implementa una interfaz (class Car implements IDrivable) tiene que proporcionar el código para todas las firmas definidas en la interfaz.

Ejemplo básico:
Tiene clases de coche y bicicleta.Tanto implementar el IDrivable interfaz:

interface IDrivable 
{ 
    void accelerate(); 
    void brake();  
} 

class Car implements IDrivable 
{ 
    void accelerate() 
    { System.out.println("Vroom"); } 

    void brake() 
    { System.out.println("Queeeeek");} 
} 

class Bike implements IDrivable 
{ 
    void accelerate() 
    { System.out.println("Rattle, Rattle, ..."); } 

    void brake() 
    { System.out.println("..."); } 
} 

Ahora vamos a suponer que usted tiene una colección de objetos, que son todos "accionables" (sus clases durante todo el implementan IDrivable):

List<IDrivable> vehicleList = new ArrayList<IDrivable>(); 
list.add(new Car()); 
list.add(new Car()); 
list.add(new Bike()); 
list.add(new Car()); 
list.add(new Bike()); 
list.add(new Bike()); 

Si ahora quiere bucle sobre esa colección, se puede confiar en el hecho, de que todos los objetos de esa colección implementa accelerate():

for(IDrivable vehicle: vehicleList) 
{ 
    vehicle.accelerate(); //this could be a bike or a car, or anything that implements IDrivable 
} 

Al llamar a ese método de interfaz no está programando a una aplicación, sino a una interfaz: un contrato que garantiza que el objetivo de la llamada implementa una determinada funcionalidad.
Se puede lograr el mismo comportamiento usando la herencia, pero derivar de una clase base común da como resultado un acoplamiento estricto que se puede evitar usando interfaces.

+2

Esta respuesta entró en mi cabeza :) –

+0

Buena explicación de las interfaces en sí mismas, pero en realidad no responde la pregunta. – Nyerguds

Cuestiones relacionadas