Valerii created GROOVY-9425:
-------------------------------
Summary: InheritConstructors: child class use property value from
base class in constructor despite have the same property
Key: GROOVY-9425
URL: https://issues.apache.org/jira/browse/GROOVY-9425
Project: Groovy
Issue Type: Question
Affects Versions: 3.0.1
Reporter: Valerii
Hi, I'm working on refactoring some Jenkins pipelines in Groovy, and stumbled
upon some behaviour which looks strange for me.
I've found a bunch of copy-pasted classes which had the same
constructors/getter, and differs only in one class property value. I've created
a base class for them, and used @groovy.transform.InheritConstructors directive
to not have several same constructors. And here I've got a trouble: when
calling one of constructors on child class, which accesses property defined on
both classes, it takes property value from parent class.
Here is the sample code:
{code:java}
class BaseClass
{
public String JSON_KEY = "boolean_param"
Boolean booleanValue
def steps
BaseClass(Boolean b = false) {
this.booleanValue = b
}
BaseClass(steps, Map param) {
this.steps = steps
steps.println param.toString()
steps.println this.JSON_KEY
if (param[JSON_KEY] != null)
this.booleanValue = param[JSON_KEY].toBoolean()
}
def get()
{
return booleanValue
}
}
@groovy.transform.InheritConstructors
class ChildClass extends BaseClass
{
final static public String JSON_KEY = "test_param"
}
BaseClass test1 = new BaseClass()
ChildClass test2 = new ChildClass(true)
println test1.get().toString()
println test2.get().toString()
println "-----------------"
map3 = [boolean_param: true]
test3 = new BaseClass(this, map3)
println test3.get()
println test3.JSON_KEY
println "-----------------"
map4 = [test_param: true]
test4 = new ChildClass(this, map4)
println test4.get()
println test4.JSON_KEY
{code}
Actual output (from either Groovy Playground or local Groovy install):
{code:java}
false
true
-----------------
[boolean_param:true]
boolean_param
true
boolean_param
-----------------
[test_param:true]
boolean_param
null
test_param{code}
Expected output:
{code:java}
false
true
-----------------
[boolean_param:true]
boolean_param
true
boolean_param
-----------------
[test_param:true]
test_param
true
test_param{code}
So, constructor with Boolean as input works as expected, but one with Map is
using property from base class despite being called on child class.
Could anybody please explain why I'm seeing this behaviour, and how to get the
desired one? I'm not a developer, so I may miss something very basic here :)
Also, if I remove JSON_KEY from base class I'm getting confusing "No such
property: JSON_KEY for class: ChildClass" exception
{code:java}
Caught: groovy.lang.MissingPropertyException: No such property: JSON_KEY for
class: ChildClass
groovy.lang.MissingPropertyException: No such property: JSON_KEY for class:
ChildClass
at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:65)
at
org.codehaus.groovy.runtime.callsite.GetEffectivePogoPropertySite.getProperty(GetEffectivePogoPropertySite.java:87)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:341)
at BaseClass.<init>(test.groovy:13)
at ChildClass.<init>(test.groovy)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown
Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at
org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:72)
at
org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:59)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:263)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:286)
at test.run(test.groovy:41)
at
groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:258)
at groovy.lang.GroovyShell.run(GroovyShell.java:364)
at groovy.lang.GroovyShell.run(GroovyShell.java:353)
at groovy.ui.GroovyMain.processOnce(GroovyMain.java:652)
at groovy.ui.GroovyMain.run(GroovyMain.java:398)
at groovy.ui.GroovyMain.access$1400(GroovyMain.java:68)
at groovy.ui.GroovyMain$GroovyCommand.process(GroovyMain.java:322)
at groovy.ui.GroovyMain.processArgs(GroovyMain.java:142)
at groovy.ui.GroovyMain.main(GroovyMain.java:115)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at
org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:111)
at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:129)
{code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)