2010-10-10 13 views
5

en C++ podemos escribir:herencia genérica en Java

#include <iostream> 

class Base1 
{ 
public: void test() { std::cout << "Base 1" << std::endl; } 
}; 

class Base2 
{ 
    public: void test() { std::cout << "Base 2" << std::endl; } 
}; 

template<class T> 
class Derived: public T 
{ 

}; 

int main() 
{ 
    Derived<Base1> d1; 
    Derived<Base2> d2; 
    d1.test(); 
    d2.test(); 
} 

Para obtener la herencia de plantilla.

¿Se puede hacer lo mismo en Java usando genéricos?

Gracias.

Editar: La adición de más información sobre mis intenciones

En mi escenario Tengo dos subclases, Sprite y AnimatedSprite (que es una subclase de Sprite). El siguiente paso es un PhysicalSprite que agrega física a los sprites, pero quiero que pueda heredar tanto de Sprite como de AnimatedSprite.

+1

+1, ¡no sabía que las plantillas C++ podían hacer eso! (Esto podría usarse para lograr efectos como composición dinámica de mixin en Scala :) – missingfaktor

+0

@missingfaktor: google para el patrón CRTP –

+0

@Armen: Este no es un ejemplo de patrón CRTP. CRTP tiene una estructura general 'clase A: B ', que no es el caso con el código de OP. – missingfaktor

Respuesta

5

Las plantillas de No. C++ son much stronger que los genéricos de Java. Los genéricos en Java son solo para asegurar el tipeo correcto durante el tiempo de compilación y no están presentes en el bytecode generado, esto se llama type erasure.

En mi situación tengo dos subclases, Sprite y AnimatedSprite (que es una subclase de Sprite). El siguiente paso es un PhysicalSprite que agrega física a los sprites, pero quiero que pueda heredar tanto de Sprite como de AnimatedSprite.

La herencia no es la única forma de reutilización de código. Este caso de uso se puede manejar también con otros patrones, como el simple decoration. Considere algo parecido a lo siguiente:

interface Sprite { ... } 
class StaticSprite implements Sprite { ... } 
class AnimatedSprite implements Sprite { ... } 

class PhysicalSprite implements Sprite, Physics { 
    PhysicalSprite(Sprite inner) { ... } 
    ... 
} 

PhysicalSprite sería en este caso el delegado de los partes de Sprite a alguna instancia de Sprite proporcionado en el constructor. Entonces sería libre de agregar su propio manejo para la parte de Física.

+0

computacional y conceptualmente :) –

+0

No estoy 100% limpio, pero supongo que funcionará. ¡Gracias! – monoceres

0

No, no exactamente de la misma manera. Pero si nos dices qué es exactamente lo que quieres hacer, estoy bastante seguro de que habrá una forma elegante de hacerlo. Simplemente no veo ninguna necesidad de plantillas/genéricos en su ejemplo.
En particular, parece que Base1 y Base2 podrían beneficiarse de las interfaces comunes con el método test.

+0

Agregué más información :) – monoceres

+0

@monoceres Bueno, los patrones de diseño no son mi lado fuerte, pero parece que ya hay algunas sugerencias (y tal vez pronto lleguen algunas personas más experimentadas que yo). –

1

Alas, no.

A diferencia de C++, que se puede pensar que emite una definición de clase diferente para cada instanciación de una plantilla, todas las instancias de un tipo genérico comparten la misma clase de tiempo de ejecución en Java y tienen las mismas definiciones de método. Los genéricos (en Java) son tiempo de compilación y no son rastreados en el tiempo de ejecución.

Por lo tanto, la especificación del lenguaje Java explicitamente forbids para especificar un parámetro de tipo que superclase o interfaz implementada:

El opcional se extiende cláusula en una declaración de clase normal, especifica la superclase directa de la clase actual.

Súper: extiende ClassType

donde ClassType es un nombre de clase calificado o no calificado (con argumentos de tipo opcional)

Soluciones provisionales

  1. uso del patrón de decorador si no necesita anular los métodos invocados por la súper clase.
  2. Genera una subclase dedicada para cada creación de instancias de la plantilla. Puede hacerlo en tiempo de ejecución utilizando, por ejemplo, Javassist o utilizando transformaciones de código fuente en tiempo de compilación.