lundi 17 juillet 2017

Designing generic type inheritance hierarchy

I am stuck while designing a class hierarchy for our application. Am not able to find any solution for this design constraints scenario.

Design requirements

(Names of classes and interfaces are over generalized to avoid unnecessary confusion due to domain specific names).

  • Entity and EntitySet: We have organization wide Entity class and an interface identifying set of entities EntitySet which enforces basic methods needed to deal with specific type of entity we deal with in our organization.
  • Method specific entity sets (Method1EntitySet and Method2EntitySet): Now there are two main methods to process this entity set. Each method defines class that implements EntitySet: Method1EntitySet and Method2EntitySet.
  • Module specific interfaces and classes:
    • Now we have different modules that are developed by different developer groups. All these modules need to use both Method1EntitySet and Method2EntitySet, however they also want these classes to have some common module specific methods. So they define interface containing module specific methods, say Module1EntitySet and
    • another pair of classes Module1Method1EntitySet and Module1Method2EntitySet, both extending corresponding method specific classes and implementing module specific interface.
    • Also each module defines its own entity Module1Entity
  • The common logic: I want to have class (CommonMethod1EntitySetLogic) which will contain common functionality (to be used by all modules) of processing Method1EntitySet. All modules dealing with Method1EntitySet will use this common class. Thus the methods in CommonMethod1EntitySetLogic class should return value of type which can be cast to ModuleXMethod1EntitySet or ModuleXEntitySet for any ModuleX from which the mothods are called. I felt this type of the returned values can be EntitySet or Method1EntitySet as they are not module specific. But this is not working as can be seen in below code.

Note: Also note that in all above class names, I have omitted the generics type specification to not cause confusion about my design requirements. But this might have lead to incorrect question. So I am providing the code below.

Code

public class Entity { }
public interface EntitySet<T extends Entity> { }
public abstract class Method1EntitySet<T extends Entity> implements EntitySet<T>{}
public abstract class Method2EntitySet<T extends Entity> implements EntitySet<T>{}
public class Module1Entity extends Entity{}
public interface Module1EntitySet extends EntitySet<Module1Entity>{}
public class Module1Method1EntitySet extends Method1EntitySet<Module1Entity> implements Module1EntitySet{}
public class Module1Method2EntitySet extends Method2EntitySet<Module1Entity> implements Module1EntitySet{}

public class CommonMethod1EntitySetLogic 
{
    EntitySet<Entity> method1EntitySetProcessor1()
    {
        Method1EntitySet<Entity> obj = null;
        return obj;
    }

    Method1EntitySet<Entity> method1EntitySetProcessor2()
    {
        Method1EntitySet<Entity> obj = null;
        return obj;
    }
}

Now that all main classes given above, below is where I am getting compile time errors as specified in comments:

public class Module1 {
    public static void main(String[] args) {
        CommonMethod1EntitySetLogic logic = new CommonMethod1EntitySetLogic();
        Module1EntitySet obj2 = logic.method1EntitySetProcessor1(); //Type mismatch: cannot convert from EntitySet<Entity> to Module1EntitySet
        Module1EntitySet obj = logic.method1EntitySetProcessor2(); //Type mismatch: cannot convert from Method1EntitySet<Entity> to Module1EntitySet
        Module1Method1EntitySet obj3 = logic.method1EntitySetProcessor1(); //Type mismatch: cannot convert from EntitySet<Entity> to Module1Method1EntitySet
        Module1Method1EntitySet obj4 = logic.method1EntitySetProcessor2(); //Type mismatch: cannot convert from Method1EntitySet<Entity> to Module1Method1EntitySet
    }
}

I understand those typecasts are invalid, but then where in design I made mistake? Primarily I feel that I am doing it right, its just that CommonMethod1EntitySetLogic needs to be parameterized with generic type parameter. But I am not able to guess exactly how do I do it. How should I generic-type-parameterize CommonMethod1EntitySetLogic? Or I am simply over complicating the things?

(The zip of the eclipse project can be found here.)

Aucun commentaire:

Enregistrer un commentaire