javainheritanceobject-composition

Mixing Composition and Inheritance in Java


Is it possible to mix composition and inheritance in Java? Fist I have some generic classes is a HAS-A (or HAS-MANY) relationship (Composition).

Generic classes:

Structure, TypeA, TypeB, TypeC, etc., where Structure is in a HAS-A relationship with TypeA, TypeB and TypeC.

But then I also have several sets of subclasses which inherit from the generic classes (Inheritance) and are in the same relationship.

Sets of subclasses:

Set 1:

Structure1, TypeA1, TypeB1, TypeC1, etc., where Structure1 is in the same HAS-A relationship with TypeA1, TypeB1 and TypeC1, just like the generic classes.

And: Structure1 extends Structure, TypeA1 extends TypeA, ..., TypeC1 extends TypeC, etc.

... until Set X:

StructureX, TypeAX, TypeBX, TypeCX, etc.

Each special structure has exactly ONE specific sub-TypeA, sub-TypeB and sub-TypeC, etc. The generic classes define some code (attributes and methods) which I would like ot reuse when dealing with special structures. The problems I am facing are best explained by the code below. (I do not know if this can somehow be solved by Java "generics" but I think not.)

/***********************************************************************************************
/ Generic Structure of Structure-Class with Instances of Generic other classes (Composition)
/***********************************************************************************************/
class Structure {

    // Substructures
    TypeA instanceA;
    TypeB instanceB;

    // Defining many methods using the instances of other generic classes like TypeA
    void setGenericAttributeOfA(int value) {
        instanceA.genericAttribute = value;
    }
    void setGenericAttributeOfB(int value) {
        instanceB.genericAttribute = value;
    }
}

class TypeA {
    int genericAttribute;
}
class TypeB {
    int genericAttribute;
}

/***********************************************************************************************
/ Specific implementation of a Structure-Class with specific implementation of the other classes (Inheritance)
/***********************************************************************************************/

// In the specific implementations I want to use the generic methods, because I do not want to 
// rewrite the code for each and every specific implementation. But they should 

class Structure1 extends Structure {

    // This will create an additional attribute instanceA of specific TypeA1, so I will end up with two instances:
    // (1) TypeA super.instanceA and (2) TypeA1 this.instanceA. But what I would like is to have only
    // one instanceA of type TypeA1 that can also be used by the global methods of the generic Structure.
    TypeA1 instanceA;

    Structure1() {
        // This creates an instance of type TypeA1, but it cannot be used in the generic methods
        // because it is hold in a separate "local" variable that is not known to the generic Structure methods
        instanceA = new TypeA1();
        // This creates an instance of type TypeB1, but it cannot access the "local" specific attributes,
        // because it is hold in a varable which is statically types as TypeB
        instanceB = new TypeB1(); 
    }

    void specificMethod() {
        setGenericAttributeOfA(42); // would fail, because instanceA of type generic TypeA is null
        instanceA.specificAttribute = 13; // works only for "local" specific attributes

        setGenericAttributeOfB(42); // works only for generic attributes
        instanceB.specificAttribute = 13; // would fail, because instanceB is statically typed as generic TypeB which does not have this attribute
        ((TypeB1)instanceB).specificAttribute = 13; // works but is an ugly work-around and over-complicated if to be used many times
    }
}

class TypeA1 extends TypeA {
    int specificAttribute;
}
class TypeB1 extends TypeB {
    int specificAttribute;
}

Solution

  • Maybe Generics can help?

    Declare Structure as generic:

    class Structure<T1 extends TypeA, T2 extends TypeB, T3 extends TypeC> {
        T1 instanceA;
        T2 instanceB;
        T3 instanceC;
    }
    

    And your specific structures will just inherit from the generic Structure by specifying type arguments:

    class Structure1 extends Structure<TypeA1, TypeB1, TypeC1> {
        // here instanceA will be of type TypeA1, instanceB will be TypeB1 etc.
    }