문제

How would I express the following type relationship in Java generics:

class MyClass<T> { }

interface MyInterface<T extends MyClass> { 
  void m1(T<Integer> argument);
  void m2(T<String> argument);
  void m3(T<?> argument);
}

without a compiler complaint. Is that even possible? I want to make sure that all methods receive the same (sub)class of MyClass while not breaking type-safety. In the domain, different subclasses og MyClass would not make sence. Do I really have to list three generic type variables like this:

class MyClass<T> { }

interface MyInterface<T1 extends MyClass<Integer>, 
   T2 extends MyClass<String>, T3 extends MyClass<?>> { 
  void m1(T1 argument);
  void m2(T2 argument);
  void m3(T3 argument);
}

I feel like this is terrible to read and does neither express my intention as nicely as I wished. This question is related to my other question on generics Raw types inside of generic definition which still confuses me. Maybe someone can help! Thank you.

도움이 되었습니까?

해결책 2

Well, I realized that I get because I cannot express this in Java:

class MyClass<T> { }

interface MyInterface<T extends MyClass> { 
  T<S> m1(S argument);
}

However, I found a rather fancy solution to this. Instead of manually upgrading my return type in every subinterface, I use Spoon to read and write the corresponding source code before compilation. The compiler sees my code as if I overrode the return types in every interface manually. This keeps my code in sync with the super interface on every Maven build and I do not have to worry about it any more.

This solution might not be for everybody, but it is the cleanest solution I could think of in the spirit of DNRY.

다른 팁

Not sure if its a good way. I feel using below method you cannot "bind" the parameters m1, m2, m3 method, instead while calling you can have privilege of using any kind of parameters be it MyClass<Integer> or MyClass<String>

public class MyClass<T> { }

interface MyOtherClass<T extends MyClass<?>> { 
  void m1(T argument);
  void m2(T argument);
  void m3(T argument);
}

And the implementer

class MyOtherClassImpl<T extends MyClass<?>> implements MyOtherClass<T> {

    @Override
    public void m1(T argument) {

    }

    @Override
    public void m2(T argument) {

    }

    @Override
    public void m3(T argument) {

    }

}

and this is how you can call

  MyOtherClass<MyClass<?>> otc = new MyOtherClassImpl<MyClass<?>>();
  MyClass<Integer> m1 = new MyClass<Integer>();
  MyClass<String> m2 = new MyClass<String>();
  MyClass<Object> m3 = new MyClass<Object>();
  otc.m1(m1);
  otc.m2(m2);
  otc.m3(m3);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top