Si implemento una interfaz, ¿se llama herencia?

31

Si mi clase es implementsuna interfaz, ¿puedo decir que estoy siguiendo la herencia? Sé que cuando una clase es extendsotra clase, entonces es herencia.

RajeeV VenkaT
fuente
77
El comentario de Jodrell es simplemente incorrecto. Implementar una interfaz es, de hecho, herencia, y heredar una interfaz de otra es herencia. ¿Como sabemos? Al definir la palabra que estamos usando. La herencia es la propiedad de que los miembros heredables de un tipo también son miembros de otro tipo. Según esta definición, claramente una clase que implementa una interfaz ha heredado todos los métodos de la interfaz; solo mire la clase y la interfaz y encontrará que en un programa correcto, tienen los mismos miembros.
Eric Lippert
Desmarqué y me fui con más confusión.
RajeeV VenkaT
18
Por lo que vale, creo que estás gastando mucho tiempo en una definición de palabras que no te dará muchos beneficios. Al final del día, todos sabemos lo que significa implementar una interfaz, y si se considera "herencia" es en gran medida irrelevante para su trabajo diario.
Robert Harvey
3
Estoy (en su mayoría) de acuerdo con Robert. Creo que hay un valor real en comprender los significados técnicos precisos de las palabras de la jerga, ya que se utilizan en diversos contextos. ¡Pero Robert tiene razón en que es mucho más beneficioso comprender el impacto práctico! ¿Cómo puedes usar la herencia para hacer tu código más seguro? ¿Más comprobable? ¿Más reutilizable? ¿Mas flexible? Y así. Saber que los miembros de los tipos base también son miembros de los tipos derivados es genial, pero es mejor saber cómo usarlo de manera efectiva.
Eric Lippert

Respuestas:

78

ACTUALIZACIÓN: He revisado esta respuesta. Se plantearon una serie de buenos puntos en los comentarios que merecían ser llamados.

Si mi clase implementa una interfaz, ¿puedo decir que estoy siguiendo la herencia?

No está del todo claro qué quieres decir con "seguir la herencia". Hagamos una pregunta un poco diferente?

¿Qué es la herencia?

  • Cuando los miembros de un tipo X se consideran miembros de otro tipo Y, los miembros de Y son heredadas de X .
  • Hay una relación de herencia entre algunos tipos; es decir, para algunos tipos X e Y decimos "Y hereda de X".

Estos son sutilmente diferentes. Eso es lamentable porque es confuso.

¿Qué confusión suele surgir de esta sutil distinción?

La confusión puede surgir porque las personas piensan en la herencia como un mecanismo para compartir detalles de implementación. Aunque es un mecanismo de este tipo, ese mecanismo funciona compartiendo miembros . ¡Esos miembros no necesitan tener implementaciones! Como veremos, pueden ser abstractos.

Personalmente, estaría más feliz si las especificaciones Java y C # usaran una palabra diferente a "hereda" para describir la relación entre los métodos de interfaz y las clases, para evitar esta confusión. Pero no lo hacen, y tenemos que razonar a partir de las especificaciones, no en contra de ellas.

En Java, ¿los miembros de la interfaz los heredan las clases que los implementan?

Si, algunos lo son. Consulte la sección 8.4.8 de la especificación de Java, que cito aquí para su conveniencia.

Una clase C hereda de su superclase directa y superinterfaces directas todos los métodos abstractos y predeterminados m para los cuales se cumple todo lo siguiente: [...]

Si dice que una clase implementa una interfaz, la clase hereda los métodos abstractos y predeterminados de esa interfaz . (Por supuesto, he omitido las condiciones que siguen; vea la especificación para más detalles. En particular, una clase que implementa un miembro de una interfaz no se considera que haya heredado ese miembro. Nuevamente, ¿es esto confuso? Sí).

¿Normalmente decimos en Java que una clase hereda de una interfaz?

Por lo general, diríamos que una clase implementa una interfaz. Como se señaló anteriormente, una clase puede heredar miembros de una interfaz, y aún así no se puede decir que herede de la interfaz. Lo cual es confuso, sí.

¿Importa esta sutil distinción en el trabajo diario?

Por lo general no. Este tipo de análisis estrecho de la especificación es más útil para los escritores de compiladores que los desarrolladores de línea de negocios. Es más importante entender cuándo usar una interfaz que obtener una definición precisa de "hereda de".

Eric Lippert
fuente
44
No puedo discutir con una referencia canónica. Cuando las especificaciones difieren, como necesariamente lo hacen, los términos simples se vuelven semánticamente sobrecargados y ambiguos fuera de contexto. La pregunta está etiquetada, javaasí que esta es la respuesta correcta, a menos que el OP se refiera a otra java:-)
Jodrell
55
Aunque la pregunta está etiquetada con Java, encuentro problemático citar una especificación de lenguaje para un término genérico. Muchos idiomas tienen interfaces y sus especificaciones de idioma pueden usar un término diferente, por lo que usar un término específico de Java puede ser confuso cuando se habla con desarrolladores que usan X-Lang.
Thomas Owens
55
@ThomasOwens: Estoy de acuerdo en que este escenario es común y estoy completamente en desacuerdo con su conclusión. La solución al problema de comunicación que describe es educar a todos los involucrados en cuanto a los significados precisos de las palabras en el contexto relevante . Existen especificaciones para proporcionar esta claridad; ¡usalos, usalos a ellos!
Eric Lippert
55
¿Por qué la especificación del lenguaje Java tiene la última palabra aquí? La especificación del lenguaje a menudo afirma cosas con las que el "desarrollador común" no está de acuerdo con respecto a la terminología.
Benjamin Gruenbaum
55
@BenjaminGruenbaum: ¿No lo sé? Esos desarrolladores están equivocados, y a menudo se encargan de "educar" a otros sobre sus creencias equivocadas. No creerías la cantidad de libros de lenguaje de programación que tuve que arreglar porque los autores tenían algunas creencias completamente locas sobre VB, C #, JavaScript, etc., que de ninguna manera eran correctas. (Jon Skeet no estaba entre ellos; ¡C # In Depth fue correcto desde el principio! Nunca he hecho tan pocos comentarios sobre un libro y todavía me han pagado).
Eric Lippert
26

Herencia significa escribir una nueva subclase para una superclase. Escribir una nueva clase en una interfaz es implementar esa interfaz. (Y escribir una nueva interfaz basada en una antigua está extendiendo esa interfaz).

El único término correcto que se aplica a las tres posibilidades es el subtipo . No todos los subtipos son subclases.

Kilian Foth
fuente
1
El libro de GoF parece considerar el término apropiado de herencia de interfaz para describir el subtipo (Sección 1.6 Clase versus herencia de interfaz)
mosquito
"Una vez asistí a una reunión del grupo de usuarios de Java donde James Gosling (el inventor de Java) fue el orador destacado. Durante la memorable sesión de preguntas y respuestas, alguien le preguntó:" Si pudieras volver a hacer Java, ¿qué cambiarías? " omita las clases ", respondió. Explicó que el verdadero problema no eran las clases per se, sino más bien la herencia de implementación (la relación extendida). La herencia de interfaz (la relación de implementos) es preferible. Debe evitar la herencia de implementación siempre que sea posible". javaworld.com/article/2073649/core-java/…
ricardoramos
1

Con subclases , tú

  • heredar el estado de la superclase (todas las variables de instancia, las vea o no)
  • heredar implementaciones reales (todos los métodos no abstractos)

Con las interfaces , completa un contrato implementando los métodos declarados.

Esa es la forma clásica de verlo. Ahora con Java 8 las interfaces se convierten en una mezcla:

  • aún no hereda el estado (ya que las interfaces aún no tienen variables de instancia)
  • ahora puede heredar implementaciones predeterminadas de la interfaz

¿Implementar una interfaz cuyos métodos tienen implementaciones predeterminadas todavía cuenta como 'implementar', o más bien como extensión? No pude decirlo. Como este caso es bastante exagerado (esto en realidad habilitó la herencia múltiple sin estado), todavía usaría 'herencia' solo con subclases.

Peter Walser
fuente