Sé que la herencia múltiple no está permitida en Java y C #. Muchos libros simplemente dicen que no se permite la herencia múltiple. Pero se puede implementar mediante interfaces. No se comenta nada sobre por qué no está permitido. ¿Alguien puede decirme con precisión por qué no está permitido?
c#
java
language-design
multiple-inheritance
Abdulsattar Mohammed
fuente
fuente
Respuestas:
La respuesta corta es: porque los diseñadores de lenguajes decidieron no hacerlo.
Básicamente, parecía que los diseñadores de .NET y Java no permitían la herencia múltiple porque razonaban que agregar MI agregaba demasiada complejidad a los lenguajes y proporcionaba muy pocos beneficios .
Para una lectura más divertida y en profundidad, hay algunos artículos disponibles en la web con entrevistas a algunos de los diseñadores del lenguaje. Por ejemplo, para .NET, Chris Brumme (que trabajó en MS en CLR) ha explicado las razones por las que decidieron no:
Puedes leer el articulo completo aquí.
Para Java, puede leer este artículo :
fuente
Herencia múltiple de implementación es lo que no está permitido.
El problema es que el compilador / tiempo de ejecución no puede averiguar qué hacer si tiene una clase Cowboy y una Artist, ambas con implementaciones para el método draw (), y luego intenta crear un nuevo tipo CowboyArtist. ¿Qué sucede cuando llamas al método draw ()? ¿Hay alguien muerto en la calle o tienes una hermosa acuarela?
Creo que se llama el problema de la herencia del doble diamante.
fuente
Razón: Java es muy popular y fácil de codificar, debido a su simplicidad.
Entonces, lo que los desarrolladores de Java se sienten difíciles y complicados de entender para los programadores, intentaron evitarlo. Uno de esos tipos de propiedad es la herencia múltiple.
Problema con la herencia múltiple: problema del diamante.
Ejemplo :
Ésta es la ambigüedad existente en el problema de los diamantes.
No es imposible resolver este problema, pero crea más confusión y complejidades al programador mientras lo lee. Causa más problemas de los que intenta resolver.
Nota : Pero de cualquier manera, siempre puede implementar la herencia múltiple indirectamente mediante el uso de interfaces.
fuente
Porque Java tiene una filosofía de diseño muy diferente a la de C ++. (No voy a hablar de C # aquí).
Al diseñar C ++, Stroustrup quería incluir funciones útiles, independientemente de cómo se pudieran usar incorrectamente. Es posible estropear en grande con herencia múltiple, sobrecarga de operadores, plantillas y varias otras características, pero también es posible hacer algunas cosas muy buenas con ellas.
La filosofía de diseño de Java es enfatizar la seguridad en las construcciones del lenguaje. El resultado es que hay cosas que son mucho más incómodas de hacer, pero puedes estar mucho más seguro de que el código que estás viendo significa lo que crees que hace.
Además, Java fue en gran medida una reacción de C ++ y Smalltalk, los lenguajes OO más conocidos. Hay muchos otros lenguajes OO (Common Lisp fue en realidad el primero en ser estandarizado), con diferentes sistemas OO que manejan mejor MI.
Sin mencionar que es completamente posible hacer MI en Java, usando interfaces, composición y delegación. Es más explícito que en C ++ y, por lo tanto, es más torpe de usar, pero le dará algo que es más probable que comprenda a primera vista.
No hay una respuesta correcta aquí. Hay diferentes respuestas, y cuál es mejor para una situación determinada depende de las aplicaciones y las preferencias individuales.
fuente
La principal (aunque no la única) razón por la que las personas se alejan de la MI es el llamado "problema del diamante" que genera ambigüedad en su implementación. Este artículo de wikipedia lo analiza y lo explica mejor que yo. MI también puede conducir a un código más complejo, y muchos diseñadores de OO afirman que no necesita MI, y si lo usa, su modelo probablemente sea incorrecto. No estoy seguro de estar de acuerdo con este último punto, pero mantener las cosas simples siempre es un buen plan.
fuente
En C ++, la herencia múltiple era un gran dolor de cabeza cuando se usaba incorrectamente. Para evitar esos problemas de diseño populares, se forzó la "herencia" de múltiples interfaces en los lenguajes modernos (java, C #).
fuente
La herencia múltiple es
Por lo tanto, se puede considerar una buena elección no incluir la herencia múltiple en el lenguaje Java.
fuente
Otra razón es que la herencia única hace que la conversión sea trivial, sin emitir instrucciones de ensamblador (aparte de verificar la compatibilidad de los tipos cuando sea necesario). Si tuviera herencia múltiple, necesitaría averiguar en qué parte de la clase secundaria comienza un determinado padre. Por tanto, el rendimiento es sin duda una ventaja (aunque no la única).
fuente
En los viejos tiempos (años 70), cuando la informática era más ciencia y menos producción en masa, los programadores tenían tiempo para pensar en un buen diseño y una buena implementación y, como resultado, los productos (programas) tenían alta calidad (por ejemplo, diseño TCP / IP e implementación ). Hoy en día, cuando todo el mundo está programando y los gerentes están cambiando las especificaciones antes de las fechas límite, los problemas sutiles como el que se describe en el enlace de wikipedia de la publicación de Steve Haigh son difíciles de rastrear; por lo tanto, la "herencia múltiple" está limitada por el diseño del compilador. Si te gusta, aún puedes usar C ++ ... y tener toda la libertad que quieras :)
fuente
Tomo la declaración de que "la herencia múltiple no está permitida en Java" con una pizca de sal.
La herencia múltiple se define cuando un "tipo" hereda de más de un "tipo". Y las interfaces también se clasifican como tipos según su comportamiento. Entonces Java tiene herencia múltiple. Solo que es más seguro.
fuente
La carga dinámica de clases dificulta la implementación de la herencia múltiple.
En Java, en realidad, evitaron la complejidad de la herencia múltiple en lugar de utilizar una interfaz y una herencia únicas. La complejidad de la herencia múltiple es muy alta en una situación como la que se explica a continuación
Problema del diamante de herencia múltiple. Tenemos dos clases B y C que heredan de A. Supongamos que B y C anulan un método heredado y proporcionan su propia implementación. Ahora D hereda tanto de B como de C haciendo herencia múltiple. D debería heredar ese método anulado, ¿jvm no puede decidir qué método anulado se utilizará?
En c ++ se utilizan funciones virtuales para manejar y tenemos que hacerlo de forma explícita.
Esto se puede evitar mediante el uso de interfaces, no hay cuerpos de método. No se pueden crear instancias de interfaces; solo se pueden implementar mediante clases o ampliar mediante otras interfaces.
fuente
En realidad, surgirá una herencia múltiple debido a la complejidad si las clases heredadas tienen la misma función. es decir, el compilador tendrá una confusión sobre cuál debe elegir (problema del diamante). Entonces, en Java, esa complejidad eliminó y dio interfaz para obtener la funcionalidad como la herencia múltiple. Podemos usar la interfaz
fuente
Java tiene concepto, es decir, polimorfismo. Hay 2 tipos de polimorfismo en java. Hay sobrecarga de métodos y anulación de métodos. Entre ellos, la anulación del método ocurre con la relación de superclase y subclase. Si estamos creando un objeto de una subclase e invocando el método de superclase, y si la subclase se extiende a más de una clase, ¿qué método de superclase debería llamarse?
O, mientras llama al constructor de superclase por
super()
, ¿a qué se llamará?Estas decisiones son imposibles con las características actuales de la API de Java. por lo que la herencia múltiple no está permitida en java.
fuente
La herencia múltiple no está permitida en Java directamente, pero sí a través de interfaces.
Razón:
Herencia múltiple: introduce más complejidad y ambigüedad.
Interfaces: interfaces son clases completamente abstractas en Java que le brindan una forma uniforme de delinear correctamente la estructura o el funcionamiento interno de su programa desde su interfaz disponible públicamente, con la consecuencia de una mayor cantidad de flexibilidad y código reutilizable, así como más control. sobre cómo crea e interactúa con otras clases.
Más precisamente, son una construcción especial en Java con la característica adicional que le permite realizar una especie de herencia múltiple, es decir, clases que se pueden convertir a más de una clase.
Tomemos un ejemplo simple.
Suponga que hay 2 superclases clases A y B con los mismos nombres de método pero diferentes funcionalidades. A través del siguiente código con la palabra clave (extiende), la herencia múltiple no es posible.
Pero a través de interfaces, con la palabra clave (implementa) la herencia múltiple es posible.
fuente
Puede encontrar la respuesta en este enlace de documentación
Si se permite la herencia múltiple y cuando crea un objeto instanciando esa clase, ese objeto heredará campos de todas las superclases de la clase. Causará dos problemas.
¿Qué pasa si los métodos o constructores de diferentes superclases instancian el mismo campo?
¿Qué método o constructor tendrá prioridad?
Aunque ahora se permite la herencia múltiple de estado, aún puede implementar
Herencia múltiple de tipo : capacidad de una clase para implementar más de una interfaz.
Herencia múltiple de implementación (a través de métodos predeterminados en interfaces): capacidad para heredar definiciones de métodos de múltiples clases
Consulte esta pregunta de SE relacionada para obtener información adicional:
Ambigüedad de herencia múltiple con interfaz
fuente
En C ++, una clase puede heredar (directa o indirectamente) de más de una clase, lo que se conoce como herencia múltiple .
C # y Java, sin embargo, limitan las clases a una herencia única que cada clase hereda de una única clase principal.
La herencia múltiple es una forma útil de crear clases que combinan aspectos de dos jerarquías de clases dispares, algo que ocurre a menudo cuando se utilizan diferentes marcos de clase dentro de una sola aplicación.
Si dos marcos definen sus propias clases base para las excepciones, por ejemplo, puede usar herencia múltiple para crear clases de excepción que se pueden usar con cualquiera de los marcos.
El problema de la herencia múltiple es que puede generar ambigüedad. El ejemplo clásico es cuando una clase hereda de otras dos clases, cada una de las cuales hereda de la misma clase:
En este ejemplo, el
flag
miembro de datos está definido porclass A
. Peroclass D
desciende declass B
yclass C
, que ambos derivan deA
, por lo que, en esencia, dos copias deflag
están disponibles debido a dos instancias deA
están enD
la jerarquía de clases 's. ¿Cuál quieres configurar? El compilador se quejará de que la referencia aflag
enD
es ambigua . Una solución es eliminar la ambigüedad explícita de la referencia:Otra solución es declarar B y C como
virtual base classes
, lo que significa que solo puede existir una copia de A en la jerarquía, eliminando cualquier ambigüedad.Existen otras complejidades con la herencia múltiple, como el orden en el que se inicializan las clases base cuando se construye un objeto derivado, o la forma en que los miembros pueden ocultarse inadvertidamente de las clases derivadas. Para evitar estas complejidades, algunos lenguajes se limitan al modelo de herencia única más simple.
Aunque esto simplifica considerablemente la herencia, también limita su utilidad porque solo las clases con un ancestro común pueden compartir comportamientos. Las interfaces mitigan un poco esta restricción al permitir que las clases en diferentes jerarquías expongan interfaces comunes incluso si no están implementadas compartiendo código.
fuente
Imagina este ejemplo: tengo una clase
Shape1
Tiene
CalcualteArea
método:Hay otra clase
Shape2
que también tiene el mismo método.Ahora tengo una clase secundaria Circle, deriva de Shape1 y Shape2;
Ahora, cuando creo un objeto para Circle y llamo al método, el sistema no sabe qué método de área de cálculo se llamará. Ambos tienen las mismas firmas. Entonces el compilador se confundirá. Por eso no se permiten herencias múltiples.
Pero puede haber varias interfaces porque las interfaces no tienen una definición de método. Incluso ambas interfaces tienen el mismo método, ambas no tienen ninguna implementación y siempre se ejecutará el método en la clase secundaria.
fuente