I see that as of Groovy 2.0 there is the possibility to add a TypeChecked
annotation to classes or methods to trigger the optional static checking.
I must admit that I am confused by how such a thing could work. The article gives simple examples such as
@TypeChecked
Date test() {
// compilation error:
// cannot assign value of Date
// to variable of type int
int object = new Date()
String[] letters = ['a', 'b', 'c']
// compilation error:
// cannot assign value of type String
// to variable of type Date
Date aDateVariable = letters[0]
// compilation error:
// cannot return value of type String
// on method returning type Date
return "today"
}
In this case it is clear that some checks will fail. But in the general case, one will use, say, the return value of method A
, that is not type checked, inside the type checked method B
. In this case I do not see how the compiler can figure out whether method B
types are consistent, since it does not have enough information on the return value of method A
.
How can one enable type checking on a subset of the code without losing type safety in general?
EDIT
I try to make an example. What if I have an old class
class Old {
public getFoo() {
return 1
}
}
and try to use it from type-checked code, like
@TypeChecked
class New {
int doubleFoo() {
return 2 * (new Old().foo)
}
}
The compiler just does not know what to do, and I guess it will fail to compile (I do not have Groovy2 installed here at work to check). But if this is the case, it become an issue to use any code written before Groovy2. So I imagine something more sophisticated is done, but I am not sure what.
There is no such problem. If you call a method from an unchecked class, then it's the declared return type which is used and the behaviour is exactly the same as if you use a Java method from Groovy.
Take the following example:
Now, imagine this:
Note that in general, you use mixed type checking in a single class if you have code which heavily relies on dynamic code that the type checker obviously cannot check. This is the case, for example, if you rely on a builder. If so, then you just declare a method which uses the builder as not checked, and the rest of your code is checked. As long as the unchecked method returns a compatible type, type safety is guaranteed.