¿Por qué no se permite la Herencia múltiple en Java o C#?


Sé que la herencia múltiple no está permitida en Java y C#. Muchos libros solo dicen, la herencia múltiple no está permitida. Pero se puede implementar mediante el uso de interfaces. Nada se discute acerca de por qué no está permitido. ¿Puede alguien decirme exactamente por qué no está permitido?

Author: Jon Schneider, 2009-06-15

17 answers

La respuesta corta es: porque los diseñadores del lenguaje 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 mientras proporcionaba muy poco beneficio.

Para una lectura más divertida y en profundidad, hay algunos artículos disponibles en la web con entrevistas de algunos de los diseñadores de idiomas. Por ejemplo, para. NET, Chris Brumme (oms trabajo en MS en el CLR) ha explicado las razones por las que decidieron no:

  1. Diferentes idiomas en realidad tienen diferentes expectativas de cómo MI obrar. Por ejemplo, cómo son los conflictos resuelto y si las bases duplicadas se fusionan o son redundantes. Antes de que podamos implementar MI en el CLR, tenemos que hacer una encuesta de todos los idiomas, figura los conceptos comunes, y decidir cómo expresarlos en un lenguaje neutral. Nosotros también tengo que decidir si MI pertenece en el CLS y lo que esto significaría para idiomas que no quieren este concepto (presumiblemente VB.NET, por ejemplo). De claro, ese es el negocio en el que estamos como un tiempo de ejecución de lenguaje común, pero no tengo que hacerlo por MI aun.

  2. El número de lugares donde MI es realmente apropiado es en realidad bastante pequeño. En muchos casos, múltiples la herencia de interfaz puede obtener el trabajo hecho en su lugar. En otros casos, usted puede ser capaz de utilizar encapsulación y delegación. Si tuviéramos que añadir un construcción ligeramente diferente, como mixins, que en realidad sería más poderoso?

  3. La herencia de implementación múltiple inyecta mucha complejidad en el aplicación. Esta complejidad impactos fundición, diseño, envío, acceso al campo, serialización, identidad comparaciones, verificabilidad, reflexión, genéricos, y probablemente muchos otros lugares.

Puedes leer el texto completo artículo aquí.

Para Java, puedes leer este artículo :

Las razones para omitir múltiples herencia del lenguaje Java en su mayoría se derivan de la " simple, objeto orientado, y familiar " objetivo. Como lenguaje simple, creadores de Java quería un lenguaje que la mayoría de los desarrolladores podría comprender sin extensa formación. Con ese fin, trabajaron para hacer que el lenguaje sea similar a C++ como posible (familiar) sin llevar sobre C++ complejidad innecesaria (simple).

En opinión de los diseñadores, múltiples la herencia causa más problemas y confusión de lo que resuelve. Así que cortaron herencia múltiple del idioma (al igual que cortan operador sobrecargar). Los diseñadores' extensa La experiencia en C++ les enseñó que la herencia múltiple simplemente no valía la pena dolor.

 131
Author: Razzie,
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-10-13 20:09:20

Herencia Múltiple de implementación es lo que no está permitido.

El problema es que el compilador/runtime no puede averiguar qué hacer si tienes una clase Cowboy y una Artist, ambas con implementaciones para el método draw (), y luego intentas 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 la herencia del doble diamante problema.

 83
Author: duffymo,
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-06-15 09:52:59

Razón: Java es muy popular y fácil de codificar, debido a su simplicidad.

Así que lo que los desarrolladores de java se sienten difíciles y complicados de entender para los programadores, trataron de evitarlo. Uno de esos tipos de propiedad es la herencia múltiple.

  1. evitaron los punteros
  2. evitaron la herencia múltiple.

Problema con herencia múltiple: Problema de diamante.

Ejemplo:

  1. Supongamos que la clase A es tener un método divertido (). la clase B y la clase C se derivan de la clase A.
  2. Y tanto las clases B como C, anulan el método fun().
  3. Ahora supongamos que la clase D hereda tanto la clase B como la C. (solo Suposición)
  4. Crear objeto para la clase D.
  5. D d = new D();
  6. e intenta acceder a d. fun (); = > ¿llamará a fun () de clase B o a fun () de clase C?

Esta es la ambigüedad existente en el problema del diamante.

No es imposible resolver este problema, pero crea más confusión y complejidades para el programador mientras lo lee. Causa más problemas de los que intenta resolver.

Nota: Pero de cualquier manera siempre puede implementar herencia múltiple indirectamente mediante el uso de interfaces.

 19
Author: user1923551,
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
2013-12-12 07:34:59

Porque Java tiene una filosofía de diseño muy diferente de C++. (No voy a hablar de C# aquí.)

En el diseño de C++, Stroustrup quería incluir características útiles, independientemente de cómo podrían ser mal utilizadas. Es posible arruinar a lo 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 un montón de otros lenguajes OO (Common Lisp fue en realidad el primero en ser estandarizado), con diferentes sistemas OO que manejan MI mejor.

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 te dará algo que es más probable que entiendas a primera vista.

Aquí no hay una respuesta correcta. Hay diferentes respuestas, y cuál es mejor para una situación dada depende de las solicitudes y las preferencias individuales.

 13
Author: David Thornley,
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-06-15 18:01:29

La razón principal (aunque de ninguna manera la única) por la que las personas se alejan de MI es el llamado "problema del diamante" que conduce a la ambigüedad en su implementación. Este artículo de wikipedia lo discute y lo explica mejor de lo que podría. 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 esté equivocado. No estoy seguro de estar de acuerdo con este último punto, pero mantener las cosas simples siempre es un buen plan.

 12
Author: Steve Haigh,
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-02-27 15:45:35

En C++ la herencia múltiple era un gran dolor de cabeza cuando se usaba incorrectamente. Para evitar esos problemas de diseño populares múltiples interfaces "herencia" fue forzada en su lugar en lenguajes modernos (java, C#).

 8
Author: inazaruk,
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-06-15 09:56:11

La herencia múltiple es

  • difícil de entender
  • difícil de depurar (por ejemplo, si mezcla clases de múltiples frameworks que tienen métodos con nombres idénticos en el fondo, pueden ocurrir sinergias bastante inesperadas)
  • fácil de usar mal
  • no realmente que útil
  • difícil de implementar, especialmente si quieres que se haga correctamente y de manera eficiente

Por lo tanto, puede considerarse una sabia elección no incluir Herencia múltiple en el lenguaje Java.

 8
Author: mfx,
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-06-15 11:14:29

Otra razón es que la herencia única hace que el casting sea trivial, no emitiendo instrucciones de ensamblador (aparte de verificar la compatibilidad de los tipos cuando sea necesario). Si tuvieras herencia múltiple, tendrías que averiguar en qué parte de la clase hijo comienza un determinado padre. Así que el rendimiento es sin duda una ventaja (aunque no la única).

 5
Author: Blindy,
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-06-15 10:02:47

Tomo la afirmació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 ya que tienen comportamiento. Así que Java tiene herencia múltiple. Sólo que es más seguro.

 4
Author: Rig Veda,
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-06-15 17:27:38

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 mediante el uso de la herencia única y la interfaz. La complejidad de la herencia múltiple es muy alta en una situación como se explica a continuación

el problema del diamante de la herencia múltiple. Tenemos dos clases B y C heredando de A. Supongamos que B y C están sobreescribiendo un método heredado y proporcionar su propia implementación. Ahora D hereda de B y C haciendo herencia múltiple. D debe heredar ese método anulado, jvm no puede decidir qué método anulado se utilizará?

En c++ se usan funciones virtuales para manejar y tenemos que hacerlo explícitamente.

Esto se puede evitar mediante el uso de interfaces, no hay cuerpos de método. Las interfaces no pueden ser instanciadas-solo pueden ser implementadas por clases o extendidas por otras interfaces.

 4
Author: sujith 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
2013-01-12 11:44:43

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 una alta calidad ( p.ej. Diseño e implementación de TCP/IP). Hoy en día, cuando todo el mundo está programando, y los gerentes están cambiando las especificaciones antes de los plazos, cuestiones sutiles como la que se describe en el enlace de wikipedia de Steve Haigh post son difíciles de rastrear; por lo tanto, la "herencia múltiple" está limitada por el diseño del compilador. Si te gusta, todavía puedes usar C++ .... y tener toda la libertad que quieras:)

 3
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
2009-06-15 10:31:10

En realidad, la herencia múltiple surgirá a la complejidad si las clases heredadas tienen la misma función. es decir, el compilador tendrá una confusión que uno tiene que elegir (problema de diamante). Así que en Java que la complejidad eliminado y dio interfaz para obtener la funcionalidad como la herencia múltiple dio. Podemos usar interfaz

 3
Author: Jinu,
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-05 09:59:44

Java tiene concepto, es decir, polimorfismo. Hay 2 tipos de polimorfismo en java. Hay sobrecarga de métodos y sobreescritura de métodos. Entre ellos, la sobreescritura de métodos ocurre con la relación de super y subclase. Si estamos creando un objeto de una subclase e invocando el método de superclass, y si la subclase extiende más de una clase, ¿qué método de superclase debería ser llamado?

O, mientras llama al constructor de superclase por super(), qué constructor de superclase obtendrá llamado?

Estas decisiones son imposibles por las características actuales de la API de Java. por lo tanto, la herencia múltiple no está permitida en Java.

 2
Author: Abhay Kokate,
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-10-30 18:04:28

La herencia múltiple no está permitida en Java directamente , pero a través de interfaces está permitida.

Razón:

Herencia múltiple: Introduce más complejidad y ambigüedad.

Interfaces: Las interfaces son clases completamente abstractas en Java que le proporcionan una forma uniforme de delinear adecuadamente 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 crear e interactuar 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 pueden transmitirse a más de una clase.

Tomemos un ejemplo simple.

  1. Supongamos 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 (extiende) la herencia múltiple de la palabra clave no es posible.

       public class A                               
         {
           void display()
             {
               System.out.println("Hello 'A' ");
             }
         }
    
       public class B                               
          {
            void display()
              {
                System.out.println("Hello 'B' ");
              }
          }
    
      public class C extends A, B    // which is not possible in java
        {
          public static void main(String args[])
            {
              C object = new C();
              object.display();  // Here there is confusion,which display() to call, method from A class or B class
            }
        }
    
  2. Pero a través de interfaces, con la palabra clave (implements) es posible la herencia múltiple.

    interface A
        {
           // display()
        }
    
    
     interface B
        {
          //display()
        }
    
     class C implements A,B
        {
           //main()
           C object = new C();
           (A)object.display();     // call A's display
    
           (B)object.display(); //call B's display
        }
    }
    
 1
Author: Chaitra Deshpande,
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-06 16:32:35

En C++ una clase puede heredar (directa o indirectamente) de más de una clase, a la que se hace referencia como herencia múltiple.

C# y Java, sin embargo, limitan las clases a herencia única cada clase hereda de una clase de padres solteros.

La herencia múltiple es una forma útil de crear clases que combinan aspectos de dos clases dispares jerarquías, algo que a menudo sucede cuando se utilizan diferentes marcos de trabajo de clase dentro de un solo aplicación.

Si dos frameworks definen sus propias clases base para excepciones, por ejemplo, puede use herencia múltiple para crear clases de excepción que se pueden usar con cualquiera de los marcos.

El problema con la herencia múltiple es que puede conducir a la 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:

class A {
    protected:
    bool flag;
};
class B : public A {};
class C : public A {};
class D : public B, public C {
    public:
    void setFlag( bool nflag ){
        flag = nflag; // ambiguous
    }
};

En este ejemplo, el miembro de datos flag se define por class A. Pero class D desciende de class B y class C, que ambos derivan de A, por lo que en esencia dos copias de flag están disponibles porque dos las instancias de A están en la jerarquía de clases de D. ¿Cuál quieres poner? El compilador se quejará que la referencia a {[2] {} en[10]} es ambigua. Una solución es desambiguar explícitamente la referencia:

B::flag = nflag;

Otra solución es declarar B y C como virtual base classes, lo que significa que solo una copia de A puede en la jerarquía, eliminando cualquier ambigüedad.

Existen otras complejidades con la herencia múltiple, como el orden en el que las clases base son inicializado cuando se construye un objeto derivado, o la forma en que los miembros se pueden ocultar inadvertidamente de clases derivadas. Para evitar estas complejidades, algunos lenguajes se limitan al modelo de herencia simple.

Aunque esto simplifica considerablemente la herencia, también limita su utilidad porque solo las clases con un ancestro común pueden compartir comportamiento. Las interfaces mitigan esto restricción algo al permitir que las clases en diferentes jerarquías expongan interfaces comunes incluso si no se implementan compartiendo código.

 1
Author: robert,
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-08-19 06:06:34

¿Puede alguien decirme exactamente por qué no está permitido?

Puede encontrar la respuesta en esta documentación enlace

Una razón por la que el lenguaje de programación Java no le permite extender más de una clase es evitar los problemas de herencia múltiple de estado, que es la capacidad de heredar campos de múltiples clases

Si se permite la herencia múltiple y cuando crea un objeto instanciando esa clase, eso el objeto heredará campos de todas las superclases de la clase. Causará dos problemas.

  1. ¿Qué pasa si los métodos o constructores de diferentes super clases instancian el mismo campo?

  2. Qué método o constructor tendrá prioridad?

Aunque ahora se permite la herencia múltiple de estado, todavía 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 de heredar definiciones de métodos de múltiples clases

Refiérase a esta pregunta relacionada SE para información adicional:

Ambigüedad de Herencia Múltiple con Interfaz

 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-05-23 12:26:23

Imagine este Ejemplo: Tengo una clase Shape1

Tiene CalcualteArea método:

Class Shape1
{

 public void CalculateArea()

     {
       //
     }
}

Hay otra clase Shape2 que también tiene el mismo método

Class Shape2
{

 public void CalculateArea()

     {

     }
}

Ahora tengo un círculo de clase hijo, que deriva de ambos Shape1 y Shape2;

public class Circle: Shape1, Shape2
{
}

Ahora, cuando creo el objeto para Circle y llamo al método, el sistema no sabe qué método de calcular área se llamará. Ambos tienen las mismas firmas. Así que el compilador se confundirá. Es por eso que las herencias múltiples no son permitir.

Pero puede haber múltiples interfaces porque las interfaces no tienen definición de método. Incluso ambas interfaces tienen el mismo método, ambos no tienen ninguna implementación y siempre se ejecutará el método en la clase hija.

 -3
Author: Engr Muhammad Enayet Abdullah,
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-11-28 06:12:44