remigiuszd
remigiuszd

Reputation: 131

groovy interpretation of `this` when inheritance applied

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

Answers (1)

Renato
Renato

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

Related Questions