2008-09-16 17 views
8

He oído que hay una forma de engañar a la herencia individual e implementar herencia múltiple en Java. ¿Alguien sabe cómo implementar esto (sin usar la interfaz)?Cheat single inheritance en Java?

Sólo por curiosidad ;-)

+0

Es una idea muy diferente. – Warrior

Respuesta

20

Puedes hacerlo, pero es complicado y deberías considerar si es lo que quieres.
La idea es utilizar la herencia basada en el alcance junto con la basada en el tipo. Lo cual es un tipo de conversación para decir que, para fines internos, las clases internas "heredan" métodos y campos de la clase externa. Es un poco como mixins, donde la clase externa está mezclada con la clase interna, pero no tan segura, ya que puedes cambiar el estado de la clase externa y usar sus métodos.
Gilad Bracha (uno de los principales diseñadores de lengua java) escribió un paper discutiendo eso. Entonces, supongamos que desea compartir algunos métodos para uso interno entre algunas clases no relacionadas (por ejemplo, para la manipulación de cadenas), puede crear sub clases de ellas como clases internas de una clase que tiene todos los métodos necesarios, y las sub clases podrían usa métodos tanto de sus súper clases como de la clase externa.

De todos modos, es complicado para clases complejas, y puede obtener la mayor parte de la funcionalidad usando importaciones estáticas (de java 5 en). Gran pregunta para entrevistas de trabajo y cuestionarios de pub, aunque ;-)

+0

Esto es lo que realmente necesitaba ... usando clases internas ... gracias – Omnipotent

+1

hay un pequeño error tipográfico aquí, lo arreglaría pero aún no tengo suficiente representante . 'crear subclases de ENTONCES como' – TygerKrash

+0

@TygerKrash No necesita representante para editar publicaciones: SE está destinado a ser como un Wiki. –

0

Java no soporta múltiples sucesiones.

Puede implementar múltiples interfaces y algunos lo ven como una forma de solucionar el problema. Personalmente, aún no he usado herencias múltiples, por lo que no puedo entender su atractivo.

Normalmente, cuando alguien sugiere herencias múltiples dentro de C# o JAVA es debido al hecho de que 'could could' in C++. Soy fanático de "solo porque no puedes querer decir que deberías". Como C# & JAVA no lo admite, ¿por qué intentarlo y obligarlo a hacer algo para lo que no fue diseñado? Esto no quiere decir que hay casos únicos en los que es una técnica válida para empoly, solo el código puede ser refactorizado para que no lo necesite.

+0

Probablemente quiera decir que no admite * herencia múltiple *. –

+0

La herencia de rasgos (esencialmente herencia mixin) en Scala muestra algunas maneras en que la herencia múltiple puede ser útil, aunque la elección de Java de no implementarla es comprensible, ya que muchas implementaciones terminan siendo innecesariamente complejas. – Calum

4

El uso de la composición en lugar de la herencia tiende a ser la forma de evitar esto. En realidad, esto también ayuda mucho con la capacidad de prueba, por lo que es una buena práctica en general.

Si solo quiere que su tipo "se comporte" como muchos otros tipos, puede heredar de tantas interfaces como desee; sin embargo, no se puede "pedir prestado" detalles de implementación de estos, obviamente.

1

Uso interface s. Puede implementar tantos como desee. Por lo general, puede usar alguna variante en el Composite Pattern (GoF) para poder reutilizar el código de implementación si eso es deseable.

3

Creo que la razón fundamental por la que Java no admite la herencia múltiple es la misma que C#; todos los objetos se derivan en última instancia de Object y tiene varias rutas a la misma clase base que es ambigua para el compilador. Ambiguous == Bad, por lo que el compilador no lo permite.

En su lugar, puede simular herencia múltiple a través de la delegación. Vea this article para un ejemplo.

+0

Compartir objeto en realidad no es ambiguo para el compilador. Solo se vuelve ambiguo cuando los métodos se definen en diferentes clases. Entonces, si una rama anula el hashcode, y el otro no. En esos casos, el programador tendrá que hacer una elección. –

2

Puede hacer trampa un poco (y enfatizo un poco) mediante el uso de instancias java.lang.reflect.Proxy.

Esto realmente solo le permite agregar interfaces adicionales y delegar sus llamadas a otra instancia en tiempo de ejecución.

Como alguien que mentores y tutores de nuevos desarrolladores me horrorizaría si alguien me mostrara el código que hizo esto. La reflexión es una de esas herramientas que realmente necesita comprender y tener una buena comprensión de Java antes de saltar. Personalmente, solo lo he hecho una vez, y era para hacer que un código que no tenía control implementara algunas interfaces. estaba esperando otro código que no tenía control (era un truco rápido, así que no tuve que escribir y mantener demasiado código de pegamento).

+0

Sí, este es un "buen truco", pero no es algo que alguien realmente debería usar en el código de producción. – Calum

+0

pero para usar Proxy necesita interfaces. OP: "... sin usar la interfaz ..." –

1

Debe tener cuidado de distinguir la herencia de la interfaz (esencialmente la herencia de un contrato para proporcionar instalaciones particulares) de la herencia de implementación (herencia de los mecanismos de implementación).

Java proporciona la herencia de interfaces por el implementos mecanismo y que puede tener múltiples herencia de interfaces.

La herencia de implementación es el mecanismo extends y solo tiene una versión única de eso. ¿Tiene realmente necesidad de herencia de implementación múltiple? Apuesto a que no, está lleno de consecuencias desagradables, a menos que seas un programador de Eiffel de todos modos.

1

Probablemente podría "simularlo" administrando explícitamente el conjunto de superclases y utilizando la reflexión para buscar todas las superclases para el método de destino. No me gustaría hacer esto en producción, pero podría ser un programa de juguete interesante. Probablemente puedas hacer muchas cosas raras aprovechando la reflexión, creando clases sobre la marcha e invocando el compilador programáticamente.

0

Estaba pensando en esto un poco más y me di cuenta de que si bien los proxies dinámicos funcionarán (¿cómo funciona RMI?), Si realmente quieres este tipo de funcionalidad, sería mejor que mires la programación orientada a aspectos (AOP) usando algo como AspectJ (eclipse.org/aspectj).

De esta manera puedes obtener varios aspectos diferentes en una clase, dándote herencia pseudo mixin, sin las jerarquías de herencia horriblemente frágiles.

Como todos han señalado, querer/necesitar herencia múltiple generalmente indica que no se está acercando al problema desde la perspectiva correcta. Recuerde el principio GoF de "¡prefiera la composición sobre la herencia" para empezar!

4

Simple La herencia múltiple no es compatible con Java, sino que tiene interfaces para cumplir el mismo propósito. En caso de que sea inflexible en el uso de la herencia múltiple, debe hacerlo en C++.

0

Al usar Inner Classes, esto es lo que C++ a veces prefiere también: Inner Class Idiom.

-1

Sí se puede decir que es un truco y es muy interesante que no se puede heredar de múltiples clases a una única clase, pero es posible implementar múltiples interfaces a una clase como

public class parents implements first, second{ 

} 

pero recuerde, usted tiene para anular los métodos declarados en las interfaces.