0

I have the following Study class that I want to be generic :

public abstract class Study<
    T1 extends Context, 
    T2 extends Region,
    T3 extends Domain<T2>, 
    T4 extends Solution> {...

Example of a derived class is as follows :

public class AmericanCultureStudy<
    T1 extends AmericanCultureContext, 
    T2 extends AmericanCultureRegion,
    T3 extends AmericanCultureDomain<T2>, 
    T4 extends AmericanCultureSolution>
extends Study<T1, T2, T3, T4> {...

public class ContemporaryAmericanCultureStudy<
    T1 extends ContemporaryAmericanCultureContext, 
    T2 extends ContemporaryAmericanCultureRegion,
    T3 extends ContemporaryAmericanCultureDomain<T2>, 
    T4 extends ContemporaryAmericanCultureSolution>
extends AmericanCultureStudy<T1, T2, T3, T4> {...

public class ContemporaryMainstreamAmericanCultureStudy<
    T1 extends ContemporaryMainstreamAmericanCultureContext, 
    T2 extends ContemporaryMainstreamAmericanCultureRegion,
    T3 extends ContemporaryMainstreamAmericanCultureDomain<T2>, 
    T4 extends ContemporaryMainstreamAmericanCultureSolution>
extends ContemporaryAmericanCultureSolution<T1, T2, T3, T4> {...

The consequence of this design is that instantiation of a class in the main code becomes heavy as follows:

ContemporaryMainstreamAmericanCultureStudy<
    ContemporaryMainstreamAmericanCultureContext, 
    ContemporaryMainstreamAmericanCultureRegion,
    ContemporaryMainstreamAmericanCultureDomain<
        ContemporaryMainstreamAmericanCultureRegion>,
        ContemporaryMainstreamAmericanCultureSolution> 
    study = new ContemporaryMainstreamAmericanCultureStudy<
        ContemporaryMainstreamAmericanCultureContext,
        ContemporaryMainstreamAmericanCultureRegion,
        ContemporaryMainstreamAmericanCultureDomain<
            ContemporaryMainstreamAmericanCultureRegion>,
        ContemporaryMainstreamAmericanCultureSolution>() ;

All classes contained in Study although different are all of a same concern type so there must be a way to make this lighter by reducing the number of types posted by Study.

Anyone can help with this? Thanks

jacobm
  • 13,790
  • 1
  • 25
  • 27
  • Try using shorter class names, packages for namespace... – John Dvorak Mar 23 '13 at 13:37
  • 1
    Do you _need_ the generics? Can't you just use `interface` or superclass without knowing the specific implementation? – Boris the Spider Mar 23 '13 at 13:44
  • 2
    There is not enough information to understand the problem you are trying to solve, but judging by the class names, you may be confusing inheritance with composition. It seems that `Context` and `Region` are attributes of `Study`. See http://stackoverflow.com/questions/11031843/inheritance-vs-composition – Christian Garbin Mar 23 '13 at 13:44
  • It looks like you 'polymorphize' a whole object graph through subtyping and generics. You probably encounter maintainability nightmares when something needs to change. But from just the class signatures it is hard to guess what the actual design might be. – nansen Mar 23 '13 at 13:44

2 Answers2

2

Are generics actually necessary in this case? Would it be possible, for instance, to just take in your constructor a group of objects of classes that derive from Context, Region, Domain, and Solution? If that's possible, it's definitely the right way to go.

If that's not possible, you might be able to at least hide some of heaviness by creating an intermediate Culture class with:

class Culture<
    C extends Context, 
    R extends Region,
    D extends Domain<R>, 
    S extends Solution> {
  ...
}

You'd need one messy declaration of, say, ContemporaryAmericanCulture, but then your Study instantiations could be Study<ContemporaryAmericanCulture> study = new Study<ContemporaryAmericanCulture>().

jacobm
  • 13,790
  • 1
  • 25
  • 27
1

At some point, it gets worth doing stuff dynamically, like having an external table like below stored in a file or database:

|ID    | Context | Region | Domain | Solution |  
|123   | Abc     | Def    | Ghi    | Jkl      |  
...

Then you can define actions/data for these entities such as what fonts to use when you print something, what page it should get redirected, how many students are allowed to be in the study etc. etc.

Your object will look like

   class Study {
       int id;
       String context;
       String region;
       String domain;
       String solution;
   }

Typesafety is all good but if you want to manage many and/or unforeseen number of entities, then you shouldn't code in a way that would require you to touch code every time an entity is added/changed/deleted.

Enno Shioji
  • 26,542
  • 13
  • 70
  • 109