Licencia MIT
La Licencia MIT es una licencia permisiva de software libre que se originó en el Instituto Tecnológico de Massachusetts a fines de la década de 1980. Como... (leer más)
La herencia múltiple es una característica de algunos lenguajes de programación informáticos orientados a objetos en los que un objeto o clase puede heredar características de más de un objeto o clase principal. Es diferente de la herencia única, donde un objeto o clase solo puede heredar de un objeto o clase en particular.
La herencia múltiple ha sido un tema controvertido durante muchos años, y los opositores señalan su mayor complejidad y ambigüedad en situaciones como el "problema del diamante", donde puede ser ambiguo en cuanto a qué clase padre un determinado La característica se hereda si más de una clase principal implementa dicha característica. Esto se puede abordar de varias maneras, incluido el uso de la herencia virtual. También se han propuesto métodos alternativos de composición de objetos que no se basan en la herencia, como mixins y rasgos, para abordar la ambigüedad.
En la programación orientada a objetos (POO), la herencia describe una relación entre dos clases en las que una clase (la clase secundaria) subclases la clase padre. El hijo hereda métodos y atributos del padre, lo que permite una funcionalidad compartida. Por ejemplo, se podría crear una clase variable Mamífero con características como comer, reproducirse, etc.; luego defina una clase secundaria Gato que herede esas funciones sin tener que programarlas explícitamente, mientras agrega nuevas funciones como perseguir ratones.
La herencia múltiple permite a los programadores usar más de una jerarquía totalmente ortogonal simultáneamente, como permitir que Gato herede de Personaje de dibujos animados y Mascota y Mamífero y acceder a funciones desde dentro de todas esas clases.
Los lenguajes que admiten herencia múltiple incluyen: C++, Common Lisp (a través de Common Lisp Object System (CLOS)), EuLisp (a través de The EuLisp Object System TELOS), Curl, Dylan, Eiffel, Logtalk, Object REXX, Scala (a través del uso de clases mixtas), OCaml, Perl, POP-11, Python, R, Raku y Tcl (integrado desde 8.6 o a través de Incremental Tcl (Incr Tcl) en versiones anteriores).
El tiempo de ejecución de IBM System Object Model (SOM) admite la herencia múltiple, y cualquier lenguaje de programación destinado a SOM puede implementar nuevas clases de SOM heredadas de varias bases.
Algunos lenguajes orientados a objetos, como Swift, Java, Fortran desde su revisión de 2003, C# y Ruby implementan herencia única, aunque los protocolos o interfaces proporcionan parte de la funcionalidad de la verdadera herencia múltiple.
PHP usa clases de rasgos para heredar implementaciones de métodos específicos. Ruby usa módulos para heredar múltiples métodos.
El "problema del diamante" (a veces denominado "Diamante mortal de la muerte") es una ambigüedad que surge cuando dos clases B y C heredan de A, y la clase D hereda tanto de B como de C. Si hay un método en A que B y C han anulado, y D no lo anula, entonces, ¿qué versión del método hereda D: la de B o la de C?
Por ejemplo, en el contexto del desarrollo de software GUI, una clase Button
puede heredar de ambas clases Rectangle
(por apariencia) y Clickable
(para funcionalidad/manejo de entrada), y las clases Rectangle
y Clickable
heredan de la clase Object
. Ahora, si se llama al método equals
para un objeto Button
y no existe tal método en la clase Button
pero hay un anulado equals
en Rectangle
o Clickable
(o ambos), ¿a qué método debería llamarse finalmente?
Se llama el "problema del diamante" debido a la forma del diagrama de herencia de clases en esta situación. En este caso, la clase A está en la parte superior, tanto B como C por separado debajo de ella, y D une las dos en la parte inferior para formar una forma de diamante.
Los lenguajes tienen diferentes formas de lidiar con estos problemas de herencia repetida.
A
, interfaces de implementación Ia
y Ib
con métodos similares que tienen implementaciones predeterminadas, tener dos métodos "heredados" con la misma firma, causando el problema del diamante. Es mitigado por tener A
para implementar el método en sí, eliminando así la ambigüedad, o obligando al llamador a lanzar primero el A
objetar a la interfaz adecuada para utilizar su aplicación predeterminada de ese método (por ejemplo, ((Ia) aInstance).Method();
).D
el objeto realmente contiene dos A
objetos y usos de A
Los miembros tienen que estar debidamente calificados. Si la herencia de A
a B
y la herencia de A
a C
ambos marcados "virtual
" (por ejemplo, "class B: virtual public A
"), C++ tiene especial cuidado para crear uno A
y usos de A
Los miembros trabajan correctamente. Si la herencia virtual y la herencia no virtual se mezclan, hay un solo virtual A
, y un no virtual A
para cada ruta de herencia no virtual A
. C++ requiere indicar explícitamente qué clase padre la característica a utilizar se invoca de i.e. Worker::Human.Age
. C++ no apoya la herencia repetida explícita ya que no habría manera de calificar qué superclase utilizar (es decir, tener una clase aparece más de una vez en una lista de derivación única [clase Dog: public Animal, Animal]). C++ también permite crear una sola instancia de la clase múltiple a través del mecanismo de herencia virtual (es decir,. Worker::Human
y Musician::Human
hará referencia al mismo objeto).D,B,C,A
, cuando B está escrito antes de C en la definición de clase. El método con las clases de argumentos más específicas es elegido (D titulado(B,C)]; luego en el orden en el que las clases de padres son nombradas en la definición de subclase (B tituladoC). Sin embargo, el programador puede anular esto, dando un orden específico de resolución de método o estableciendo una regla para combinar métodos. Esto se llama combinación de método, que puede ser totalmente controlado. El MOP (protocolo de metaobjeto) también proporciona medios para modificar la herencia, envío dinámico, instantánea de clase y otros mecanismos internos sin afectar la estabilidad del sistema.D
dos estructuras B
y C
que ambos tienen un método F()
, así satisfacer una interfaz A
, el compilador se quejará de un "e selector ambicioso" si D.F()
se llama, o si una instancia D
se asigna a una variable de tipo A
. B
y C
's métodos se pueden llamar explícitamente D.B.F()
o D.C.F()
.A,B,C
son interfaces, B,C
puede cada uno proporcionar una aplicación diferente a un método abstracto A
, causando el problema del diamante. Cualquier clase D
debe reimplementar el método (el cuerpo del cual simplemente puede enviar la llamada a una de las super implementaciones), o la ambigüedad será rechazada como un error compilado. Antes de Java 8, Java no estaba sujeto al riesgo de problema de Diamantes, porque no soportaba múltiples métodos de herencia e interfaz por defecto no estaban disponibles.(individual as Person).printInfo();
. super.someMethod()
B
y sus antepasados se verían antes de clase C
y sus antepasados, así el método A
se heredaría mediante B
. Esto es compartido con Io y Picolisp. En Perl, este comportamiento puede ser anulado usando el mro
u otros módulos para usar linearización C3 u otros algoritmos.object
. Python crea una lista de clases usando el algoritmo de linearización C3 (o Orden de Resolución de Métodos (MRO). Ese algoritmo impone dos limitaciones: los niños preceden a sus padres y si una clase hereda de múltiples clases, se mantienen en el orden especificado en el tuple de clases base (aunque en este caso, algunas clases altas en el gráfico de la herencia pueden preceder a clases inferiores en el gráfico). Así, la orden de resolución del método es: D
, B
, C
, A
.D
, C
, A
, B
, A
], que reduce a [D
, C
, B
, A
].Los lenguajes que solo permiten herencia única, donde una clase solo puede derivar de una clase base, no tienen el problema del diamante. La razón de esto es que dichos lenguajes tienen como máximo una implementación de cualquier método en cualquier nivel de la cadena de herencia, independientemente de la repetición o ubicación de los métodos. Por lo general, estos lenguajes permiten que las clases implementen múltiples protocolos, llamados interfaces en Java. Estos protocolos definen métodos pero no proporcionan implementaciones concretas. Esta estrategia ha sido utilizada por ActionScript, C#, D, Java, Nemerle, Object Pascal, Objective-C, Smalltalk, Swift y PHP. Todos estos lenguajes permiten que las clases implementen múltiples protocolos.
Además, Ada, C#, Java, Object Pascal, Objective-C, Swift y PHP permiten la herencia múltiple de interfaces (llamados protocolos en Objective-C y Swift). Las interfaces son como clases base abstractas que especifican firmas de métodos sin implementar ningún comportamiento. (Las interfaces "puras", como las de Java hasta la versión 7, no permiten ninguna implementación o datos de instancia en la interfaz). Sin embargo, incluso cuando varias interfaces declaran la misma firma de método, tan pronto como ese método está implementado (definido) en cualquier parte de la cadena de herencia, anula cualquier implementación de ese método en la cadena anterior (en sus superclases). Por lo tanto, en cualquier nivel dado de la cadena de herencia, puede haber como máximo una implementación de cualquier método. Por lo tanto, la implementación del método de herencia única no presenta el Problema del Diamante, incluso con la herencia múltiple de interfaces. Con la introducción de la implementación predeterminada para las interfaces en Java 8 y C# 8, todavía es posible generar un problema Diamond, aunque esto solo aparecerá como un error en tiempo de compilación.
La Licencia MIT es una licencia permisiva de software libre que se originó en el Instituto Tecnológico de Massachusetts a fines de la década de 1980. Como... (leer más)
Una plataforma informática o plataforma digital es un entorno en el que se ejecuta una pieza de software. Puede ser el hardware o el sistema operativo... (leer más)
La esencia de la abstracción es preservar la información relevante en un contexto dado, y olvidar la información que es irrelevante en ese... (leer más)