Returning subclass object from superclass method

▼魔方 西西 提交于 2019-12-08 17:13:06

问题


I keep coming back to variants of this problem: it probably has a very simple solution, but I can't seem to figure it out...

I have a bunch of classes of the form xQuantity, e.g. DistanceQuantity, AreaQuantity, etc., which extend a class DimensionQuantity. Now you can add or subtract DistanceQuantity's or AreaQuantity's, etc., but you can't mix them, so I think I need to have (short) add, subtract, etc., methods in the subclasses, but I want to reduce any logic duplication to a minimum. However, I need to return an object of the subclass, and this seems difficult to do from the superclass method. I believe this can be done using reflection, but AFAIK you still need to do a cast at the end in the subclass method, and I am told that reflection can be expensive... The best I have come up with so far is:

In DistanceQuantity (and the other similar ones):

public DistanceQuantity() {     
}

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

In DimensionQuantity (minus some less relevant statements):

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;   
}

Can anyone come up with leaner code - that is still type-safe? TIA


回答1:


You can use Generics like this :

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

and you extends it like this :

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

And for the initial question, it's a really bad idea (and a bad practice) to have a superclass which uses one of its sub-classes.


Resources :

  • Oracle.com - Generics

On the same topic :

  • Resource for learning Java generics?



回答2:


In Java 6, you can try something like that. But using generics is also a good 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);
    }
}



回答3:


Create an enum for the Dimensions:

public enum Dimension { AREA, DISTANCE,...}

Throw away your subclasses. Instead create only DimensionQuantity objects, and force each to have an (immutable) Dimension, set at create time.

Implement addition in DimensionQuantity, first checking that the Dimensions of the two quantities being added are the same.

Voila! Fewer classes, type safety, no duplicate code.



来源:https://stackoverflow.com/questions/3603446/returning-subclass-object-from-superclass-method

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!