2010-08-30 21 views
7

sigo volviendo a variantes de este problema: es probable que tenga una solución muy simple, pero me parece que no puede averiguarlo ...objeto de subclase del método de la superclase

que tienen un montón de clases de la forma xCantidad, por ejemplo DistanceQuantity, AreaQuantity, etc., que extienden una clase DimensionQuantity. Ahora puede sumar o restar DistanceQuantity o AreaQuantity, etc., pero no puede mezclarlos, así que creo que necesito tener métodos (cortos) para sumar, restar, etc. en las subclases, pero quiero reducir cualquier lógica duplicación a un mínimo. Sin embargo, necesito devolver un objeto de la subclase, y esto parece difícil de hacer desde el método de la superclase. Creo que esto se puede hacer usando la reflexión, pero AFAIK todavía necesita hacer un molde al final en el método de la subclase, y me dicen que la reflexión puede ser costosa ... Lo mejor que he encontrado hasta ahora es:

En DistanceQuantity (y los otros similares):

public DistanceQuantity() {  
} 

public DistanceQuantity add(DistanceQuantity d1) { 
    DistanceQuantity dn = new DistanceQuantity(); 
    Object o = super.add(dn, this, d1, DistanceUnit.REF_UNIT); 
    return (DistanceQuantity) o; 
} 

En DimensionQuantity (menos algunos estados menos relevantes):

public Object add(DimensionQuantity dn, DimensionQuantity d1, DimensionQuantity d2, 
    AbstractUnit au) { 
    dn.unit = au; 
    dn.scalar = d1.scalar + d2.scalar; 
    dn.units = dn.scalar;  
    return dn; 
} 

¿alguien puede subir con código más delgado - que sigue siendo de tipo ¿seguro? TIA

Respuesta

8

Puede utilizar los genéricos como esto:

public abstract class DimensionQuantity<T extends DimensionQuantity>{ 
    public abstract T add(T parameter); 
} 

y que se extiende de esta manera:

public class DistanceQuantity extends DimensionQuantity<DistanceQuantity>{ 
    public DistanceQuantity add(DistanceQuantity parameter){ 
     //Whatever 
     return null; 
    } 
} 

Y para la pregunta inicial, que es una muy mala idea (y una mala práctica) para tener una superclase que usa una de sus subclases.


Recursos:

Sobre el mismo tema:

+0

es mejor (más claro una vez que tienes muchos genéricos) para nombrar los genéricos algo más cercano a T_DimensionQuantity – Egwor

+0

Has olvidado la palabra clave abstracta. ;) Solo el uso de 'T' es una práctica bastante estándar, creo. – Michael

+0

@mangst gracias, es abstracto ahora. @Egwor, como dijo @mangst, T es común. T para Type, en Collection es E para Element, en Map es K y V para Key y Value. Por lo general, es la primera letra de su significado genérico. –

0

En Java 6, puede intentar algo como eso. Pero el uso de los genéricos es también una buena idea:

public abstract class DimensionQuantity { 

    protected int quantity; 

    public DimensionQuantity (int quantity) { 
     this.quantity = quantity; 
    } 

    public abstract DimensionQuantity add(DimensionQuantity dq); 
} 

public class DistanceQuantity extends DimensionQuantity { 

    public DistanceQuantity(Quantity quantity) { 
     super(quantity); 
    } 

    /* 
    * A sub-class as return type is authorized. 
    * If dq is not a DistanceQuantity, a ClassCastException is thrown, but you can change this. 
    */ 
    @Override 
    public DistanceQuantity add(DimensionQuantity dq) throws ClassCastException { 
     return new DistanceQuantity(this.quantity + (DistanceQuantity) dq.quantity); 
    } 
} 
+0

Pero ahora puede agregar una cantidad de área a sucantidad de distancia. –

+0

Sí, pero esto dará como resultado una ClassCastException. Por lo tanto, esta acción está prohibida y se detectará rápidamente (pero en tiempo de ejecución y no en una compilación). –

+0

Es realmente peligroso, y si transfiere su Quantitud de distancia a una DimensiónCantidad, ni siquiera sabe qué hacer sin arriesgar un CCE. –

0

Crear una enumeración de las Dimensiones:

public enum {Dimensión superficie, la distancia, ...}

de deshacerse de su subclases. En su lugar, cree solo objetos DimensionQuantity y forzar a cada uno a tener una Dimensión (inmutable), establecida en crear tiempo.

Implemente la adición en DimensionQuantity, primero verificando que las dimensiones de las dos cantidades que se agregan son las mismas.

Voila! Menos clases, tipo de seguridad, sin código duplicado.

+0

"primero comprobando que las Dimensiones de las dos cantidades que se agregan son las mismas." - ¡eso suena como tiempo de ejecución para mí! –

Cuestiones relacionadas