stringtranslate.com

Herencia múltiple

La herencia múltiple es una característica de algunos lenguajes de programación informática orientados a objetos en la que un objeto o una clase pueden heredar características de más de un objeto o una clase padre . Es distinta de la herencia simple, en la que un objeto o una clase solo pueden heredar de un objeto o una clase en particular.

La herencia múltiple ha sido un tema controvertido durante muchos años, [1] [2] con oponentes que señalan su creciente complejidad y ambigüedad en situaciones como el "problema del diamante", donde puede ser ambiguo en cuanto a qué clase padre se hereda una característica particular si más de una clase padre implementa dicha característica. Esto se puede abordar de varias maneras, incluido el uso de herencia virtual . [3] 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.

Detalles

En programación orientada a objetos (POO), la herencia describe una relación entre dos clases en la que una clase (la clase hija ) es una subclase de la clase padre . La clase hija hereda los métodos y atributos de la clase padre, lo que permite compartir la funcionalidad. Por ejemplo, se podría crear una clase variable Mammal con características como comer, reproducirse, etc.; luego, definir una clase hija Cat que herede esas características sin tener que programarlas explícitamente, mientras agrega nuevas características como perseguir ratones .

La herencia múltiple permite a los programadores utilizar más de una jerarquía totalmente ortogonal simultáneamente, como por ejemplo permitir que Gato herede de Personaje de dibujos animados , Mascota y Mamífero y acceda a características desde dentro de todas esas clases.

Implementaciones

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 mixin ), 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 [4] [5] ).

El entorno de ejecución de IBM System Object Model (SOM) admite herencia múltiple, y cualquier lenguaje de programación orientado a SOM puede implementar nuevas clases SOM heredadas de múltiples 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 algunas de las funciones de la verdadera herencia múltiple.

PHP utiliza clases de rasgos para heredar implementaciones de métodos específicos. Ruby utiliza módulos para heredar múltiples métodos.

El problema del diamante

Un diagrama de herencia de clases de diamante.

El " problema del diamante " (a veces denominado el "diamante mortal de la muerte" [6] ) 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 de GUI , una clase puede heredar de ambas clases (para la apariencia) y (para la funcionalidad/manejo de entrada), y las clases y ambas heredan de la clase. Ahora bien, si se llama al método para un objeto y no existe dicho método en la clase, pero hay un método anulado en o (o en ambas), ¿qué método debería ser el que se llame finalmente?ButtonRectangleClickableRectangleClickableObjectequalsButtonButtonequalsRectangleClickable

Se denomina "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 un diamante.

Mitigación

Los idiomas tienen diferentes formas de abordar estos problemas de herencia repetida.

Los lenguajes que solo permiten una herencia simple , 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. Normalmente, 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 . [13] 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 (llamadas 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 se implementa (define) en cualquier parte de la cadena de herencia, anula cualquier implementación de ese método en la cadena superior (en sus superclases). Por lo tanto, en cualquier nivel dado en la cadena de herencia, puede haber como máximo una implementación de cualquier método. Por lo tanto, la implementación de un método de herencia única no presenta el Problema de Diamante incluso con herencia múltiple de interfaces. Con la introducción de la implementación predeterminada para interfaces en Java 8 y C# 8, aún es posible generar un Problema de Diamante, aunque esto solo aparecerá como un error de tiempo de compilación.

Véase también

Referencias

  1. ^ Cargill, TA (invierno de 1991). "Controversia: el caso contra la herencia múltiple en C++". Sistemas informáticos . 4 (1): 69–82.
  2. ^ Waldo, Jim (primavera de 1991). "Controversia: el caso de la herencia múltiple en C++". Sistemas informáticos . 4 (2): 157–171.
  3. ^ Schärli, Nathanael; Ducasse, Stéphane; Nierstrasz, Oscar; Black, Andrew. "Rasgos: unidades componibles de comportamiento" (PDF) . Web.cecs.pdx.edu . Consultado el 21 de octubre de 2016 .
  4. ^ "incr Tcl". blog.tcl.tk . Consultado el 14 de abril de 2020 .
  5. ^ "Introducción al lenguaje de programación Tcl". www2.lib.uchicago.edu . Consultado el 14 de abril de 2020 .
  6. ^ Martin, Robert C. (9 de marzo de 1997). "Java y C++: una comparación crítica" (PDF) . Objectmentor.com . Archivado desde el original (PDF) el 24 de octubre de 2005. Consultado el 21 de octubre de 2016 .
  7. ^ "Estándar ECMA-367". Ecma-international.org . Consultado el 21 de octubre de 2016 .
  8. ^ "Estado de Lambda". Cr.openjdk.java.net . Consultado el 21 de octubre de 2016 .
  9. ^ "perlobj". perldoc.perl.org . Consultado el 21 de octubre de 2016 .
  10. ^ Resumen. "El orden de resolución de métodos de Python 2.3". Python.org . Consultado el 21 de octubre de 2016 .
  11. ^ "Unificación de tipos y clases en Python 2.2". Python.org . Consultado el 21 de octubre de 2016 .
  12. ^ "Página de manual de la clase". Tcl.tk . 16 de noviembre de 1999 . Consultado el 21 de octubre de 2016 .
  13. ^ "Interfaces de objetos - Manual". PHP.net . 2007-07-04 . Consultado el 2016-10-21 .

Lectura adicional

Enlaces externos