I get a compile error in Groovy 1.5.6 and I think it is a problem with type erasure. Does anyone know if I'm doing something wrong here? Or can I not do this in Groovy?
(Apologies in advance if the code formatting is bad)
I have a Groovy implementation of a Java interface which fails to compile. The Java interface in turn extends two other Java interfaces, both of which have generic types.
If I define everything in Groovy then it works... I have a Validator and Transformer interface, and a ValidatingTransformer interface which extends them both:
interface Validator <T, U> {
U isValid(T target);
}
interface Transformer<T, U> {
U transform(T target);
}
interface ValidatingTransformer<T, U, V> extends Validator<T, U>, Transformer<T, V> {
}
So long as these interfaces are all defined in Groovy, then I can implement the ValidatingTransformer with a Groovy object and the object compiles:
class ValidatingTransformerImpl implements ValidatingTransformer<String, Boolean, Integer> {
public Boolean isValid(String target) {
return null // do some validation
}
public Integer transform(String target) {
return null // do some transformation
}
}
However, if I define Validator, Transformer, and ValidatingTransformer as Java objects, then the ValidatingTransformerImpl fails to compile with the following error message: "Can't have an abstract method in a non-abstract class. The class 'ValidatingTransformerImpl' must be declared abstract or the method 'java.lang.Object transorm(java.lang.Object)' must be implemented", and a similar message for the isValid method.
So, the interface methods clearly have their types erased to objects as one would expect. So once the Java is compiled, then the Groovy compiler tries to match the methods in ValidatingTransformerImpl with an Object signature and they aren't found... the ValidatingTransformerImpl does not have those methods because it's types aren't erased yet. Is that correct?
For my project, the interfaces _must_ be declared in Java because of our architectural rules about having a one way compile time dependency between Java and Groovy. One workaround is for the ValidatingTransformerImpl to implement both the parent interfaces separately and abandon the idea of a ValidatingTransformer; however, this is undesirable because it would force calling code to maintain two references to the same object: once as a validator and once as a transformer. A workaround that does work for us is to redefine the transform() and isValid() method in the ValidatingTransformer interface. This will trigger the Groovy code to compile but I don't exactly know why this works.
Is this a defect?
Why isn't this compiling?
Why does redefining the interface methods in ValidatingTransformer work?
Thanks in advance,
Hamlet D'Arcy
--
Hamlet D'Arcy