Search code examples
javalistinheritancesubclasscovariance

Best practices for class/subclass composite of another class/subclass respectively in JAVA (android) which involve list<class/subclass> return methods


For example, suppose I have a class

class Engine {
    int horsepower;
    ...
}

and subclass

class EngineTurbo extends Engine {
    Some turbineProperty;
    ...
}

on the other hand, I have a class (with some List return method)

class Plane {
    Engine[] planeEngines;
    ...

    public List<Engine> getListOfEngines() { ... }
}

and here is my question, having this subclass:

class PlaneTurbo extends Plane {
    EngineTurbo[] planeEngines;    // yes or no?
    ...

    public PlaneTurbo(int quantity){
        planeEngines = new EngineTurbo[quantity];    // yes? or...
        super.planeEngines = new EngineTurbo[quantity];
    }

    public List<EngineTurbo> getListOfEngines() { ... }    // best practices here
}

I'd like to know about best practices on the return List < SubClass > case. I found some answers about using List < ? extends Engine > and something like that

Also found this terrific help (I share with all of you) but still I'm looking for best solution for this case

Thanks

Ah, BTW, after all of this I have another class (not subclass, or maybe yes), like...

class HangarOnlyTurboPlanes {
    List<PlaneTurbo> turboPlanes;    // only PlaneTurbo, not need Plane
    ... 
    public void someLogicInvolvingOnlyTurboPlanes(){
        List<EngineTurbo> engines = turboPlanes.get(some).getListOfEngines();
        ...
    }
}

If you are asking why, I'm working with "TURBO" app, but I like to keep it open to future another upperClass apps (maybe just Hangar) and/or siblingClass app (maybe SpaceEngineHangar whatever)

Thanks again


Solution

  • Your example is a candidate for generics. Where Plane will have reference not to concrete Engine but to a generics subclass of Engine that are specified by sub classes of Plane.

    Change your Plane to be generic:

    public class Plane<E extends Engine> {
        E[] planeEngines;
    
        public List<E> getListOfEngines() {return Arrays.asList(planeEngines);}
    }
    

    Then in your subclass all you have to do is specify concrete type of Engine and dont need to define a new variable to just hold EngineTurbo list:

    public class PlaneTurbo extends Plane<EngineTurbo> {
        public PlaneTurbo(int quantity) {
            planeEngines = new EngineTurbo[quantity];
        }
    }
    

    And finally your can get your EngineTurbo from PlaneTurbo without the need to define a new method that only returns EngineTurbo or some type of cast:

    PlaneTurbo pt = new PlaneTurbo(5);        
    List<EngineTurbo> ets = pt.getListOfEngines();