Generic class with two class hierarchies

Viewed 271

I have the following Java generics question

I have the following generic class thay may be sketched as:

public class MyClass<T> {
    AnotherClass<T> another;
    OtherClass<T> other;
    ...
}

where ... represents code that is not relevant to the case.

For the class MyClass<T> is not as important which exact type T is (as of now) but for both:

  • AnotherClass<T>

  • OtherClass<T>

is absolutely crucial what the generic type is and decisions will be made at runtime in base of that.

Based on that, the type T is not completely arbitrary, it may be either an instance of a hierarchy of classes T_1 or a hierarchy of classes T_2.

As is defined the class, the type T is equivalent to Object but I know that is equivalent to either T_1 or T_2

There is not businnes relation between entities T_1 and T_2 therefore I'm not doing:

public interface BaseT { ... }
public class T_1 implements BaseT { ... }
public class T_2 implements BaseT { ... }

public class MyClass<T extends BaseT>

Clarification about why using a generic if they are unrelated:

I'm defining (trying to) a generic class for both because even they are unrelated explictly, there is a implicit relation because both T_1 and T_2 can and will appear associated to the entity represented in MyClass

T will be the same for MyClass, AnotherClass and OtherClass so that in a instance there will only be either T_1 or T_2 but never both at the same time.

My question is, which alternatives do I have here other than design an interface for MyClass and implement it for both T_1 and T_2?.

Can I achieve something like MyClass<T extends T_1 or T_2>?

Kind regards

2 Answers

Probably, this is not exactly what your're looking for, but you might give it a try:

Create an abstract generic class that implements everything:

public abstract class MyClass<T>
{
  AnotherClass<T> another;
  OtherClass<T> other;

  // Add any code needed

}

Then create 2 generic classes for both base classes.
These classes may be empty if all code can be implemented in the abstract one:

public class MyT1Class<T extends T_1> extends MyClass<T>
{
}

public class MyT2Class<T extends T_2> extends MyClass<T>
{
}

I know it's not a very good answer but I couldn't leave it as a comment to the question.
You can check the type at runtime by trying the following:

public class MyClass<T>
{
  // This factory-method creates an instance of the class if the correct type is passed
  // It throws a RuntimeException if not.
  public static <T> MyClass<T> getInstance(Class<T> type)
  {
    if (T_1.class.isAssignableFrom(type) || T_2.class.isAssignableFrom(type))
      return (new MyClass<T>());
    else
      throw new RuntimeException("Cannot create instance of MyClass<" + type.getName() + ">");
  }

  ...

}

Then

class T_3 extends T_2
{
}

....

MyClass<T_3> test_1;
test_1 = MyClass.getInstance(T_3.class); // This will succeed

MyClass<String> test_2;
test_2 = MyClass.getInstance(String.class); // Fails
Related