Hi everyone,
I recently switched some classes in my framework from @CompileStatic to
@TypeChecked (e.g. to get dynamic call site selection), and am still
facing the problem that method/ctor calls where passing null for
arguments is valid*, fail with ambigous overloading runtime errors.
These cases of course work in the @CompileStatic case, since call site
selection is static and dependent on the type of the parameter, but fail
in the @TypeChecked case, since the null value does not carry type
information. Groovy introduced explicit type cast support for these
cases a while back, and I have started to refactor my code to do this,
but it is very noisy/inconvenient/inelegant. So I am wondering if it
would not make sense to use the parameter type from the method signature
to decide on what method to call in the dynamic case, if the parameter
value is null (basically like in the @CompileStatic case, only at
runtime in this special case) ?
Samples (Goo1 is not a subtype of Goo0):
@TypeChecked
class Goo {
def callFoo_Fails(Goo0 g0) { foo(g0) } // Expectation for g0 ==
null case: foo(Goo0) gets called; actual: Fails during runtime with
ambigous method GroovyRuntimeError
def callFoo_Works(Goo0 g0) { foo((Goo0) g0) }
def foo(Goo0 g0) { ... }
def foo(Goo1 g1) { ... }
}
or
@TypeChecked
class Goo {
static createGoo_Fails(Goo0 g0 = null) { new Goo(g0) } //
Expectation for g0 == null case: Goo(Goo0) ctor gets called; actual:
Fails during runtime with ambigous ctor GroovyRuntimeError
static createGoo_Works(Goo0 g0 = null) { new Goo((Goo0) g0) }
Goo(Goo0 g0) { ... }
Goo(Goo1 g1) { ... }
}
Cheers,
mg
*Mostly to indicate the use of a default value; this avoids the problem
of having to change a lot of signatures if the default value needs to
change, for methods with a deep call hierarchy.