Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy Generics problems with <T extends SuperClass>

class TestClass <T extends SuperClass>{
 public List<T> doSmth(){
    ///....
    List testObjects = []
    testObjects.add(new T(arg))
   return testObjects;
 }
}

class SuperClass{

}
class A extends SuperClass{
 A(Arg arg){
  ....
}
class B extends SuperClass{
 B(Arg arg){
  ....
}

////////test
class Main{
 List <A> a
 List <B> b

 Main(){
  this.a = new TestClass<A>().doSmth()
  this.b = new TestClass<B>().doSmth()
 }
}

Exception found (groovy.lang.GroovyRuntimeException: Could not find matching constructor for SuperClass) on line

 testObjects.add(new T(arg))

This is quite correct coz SuperClass have no constructor. But sub-classes have one and all of them have the same signature, arg with the same type.

can some one help me to find a solution to my problem?

like image 622
Andrew Stepanov Avatar asked Apr 02 '16 08:04

Andrew Stepanov


1 Answers

The reason why your code doesn't work is not matching constructors of A and B. The reason is missing constructor that accepts string in SuperClass.
new T() doesn't work as you expect. In your code it becomes new SuperClass(arg). The following code demonstrates it

class TestClass <T extends SuperClass> {
    public void doSmth(){
        println new T().class.simpleName;
    }
}

class SuperClass{}
class A extends SuperClass{}
class B extends SuperClass{}

new TestClass<A>().doSmth()
new TestClass<B>().doSmth()
new TestClass<String>().doSmth() //even this works

Output is

SuperClass
SuperClass
SuperClass

TestClass <T> will print Object. TestClass <T extends A> will print A and so on.

Groovy doesn't have generic type information in runtime. Groovy even doesn't do compile type checking (example with new TestClass<String>()). But it keeps some info to make new T() work.

Java's generics implementation incorporates a feature known as "type erasure" which "throws away" generic type information after completing static type checking. This allows Java to easily integrate with legacy "non-generics" libraries. Groovy currently does a little further and throws away generics information "at the source level". Generics information is kept within signatures where appropriate http://web.archive.org/web/20150102195947/http://groovy.codehaus.org/Generics

like image 75
Evgeny Avatar answered Sep 17 '22 10:09

Evgeny