Reputation: 131
Given simple code
class Parent {
private String name
Parent(String name) {
Parent o = this
o.name = name
}
}
class Child extends Parent {
Child(String name) {
super(name)
}
}
@Test
void a() {
new Child('a')
}
When compiled and run with groovy it fails with groovy.lang.MissingPropertyException: No such property: name for class: com.example.Child
When compiled and run as plain java it works. Is it a bug in groovy or is it intended behavior?
Upvotes: 1
Views: 205
Reputation: 13690
This is a result of Groovy using multiple dispatch (or multi-methods) rather than Java's static dispatch.
This means that the method Groovy will call depends on the runtime type of the object, not its static type.
In your example, Groovy is trying to call o.setName(a)
where o
has type Child
(even if you only declare it with Parent
type... that's what it means to use the runtime type to dispatch methods!).
You can fix this by using @CompileStatic
, which changes the semantics to be like Java's static dispatch (which can cause surprising behaviour sometimes, but it's much faster).
This example works fine:
import groovy.transform.CompileStatic
@CompileStatic
class Parent {
private String name
Parent(String name) {
Parent o = this
o.@name = name
}
String toString() { "Parent($name)" }
}
class Child extends Parent {
Child(String name) {
super(name)
}
}
new Child('b')
Notice that I also had to change assignment to use the field-access syntax: o.@name = name
because otherwise Groovy would try to call o.setName(name)
, but because the field is private, that method would not have been generated by Groovy.
Upvotes: 2