You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Paul King (Jira)" <ji...@apache.org> on 2020/08/06 10:33:00 UTC

[jira] [Commented] (GROOVY-9425) InheritConstructors: child class use property value from base class in constructor despite have the same property

    [ https://issues.apache.org/jira/browse/GROOVY-9425?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17172223#comment-17172223 ] 

Paul King commented on GROOVY-9425:
-----------------------------------

I am not really sure what you are after. Perhaps you want something like:
{code}
class BaseClass {
    String key() { "boolean_param" }
    Boolean booleanValue
    def steps

    BaseClass(Boolean b = false) {
        booleanValue = b
    }

    BaseClass(steps, Map param) {
        this.steps = steps
        println key()
        if (param[key()] != null)
            booleanValue = param[key()].toBoolean()
    }
}

@groovy.transform.InheritConstructors
class ChildClass extends BaseClass {
    String key() { "test_param" }
}

def test1 = new BaseClass()
def test2 = new ChildClass(true)
println test1.booleanValue
println test2.booleanValue

println "-----------------"
def test3 = new BaseClass(this, [boolean_param: true])
println test3.booleanValue
println test3.key()

println "-----------------"
def test4 = new ChildClass(this, [test_param: true])
println test4.booleanValue
println test4.key()
{code}
which yields:
{noformat}
false
true
-----------------
boolean_param
true
boolean_param
-----------------
test_param
true
test_param
{noformat}

> 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
>            Priority: Minor
>
> 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)