You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "William Woodman (Jira)" <ji...@apache.org> on 2021/12/21 15:16:00 UTC

[jira] [Comment Edited] (GROOVY-10392) Inconsistent metaClass capability for .static properties and methods vs ordinary dynamic properties and methods

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

William Woodman edited comment on GROOVY-10392 at 12/21/21, 3:15 PM:
---------------------------------------------------------------------

ok - this is not perfect by any means - but i've created a WillsExpando that offers what i feel would be relatively symetric logical behaviour 

 

it separates the extension props/methods  and statics props methods into maps - and then implements getProperty() getMethod() to intercept calls and provides propertyMissing etc to add these into the right map.

 

Had  fiddle trying to make the getMetaProperties () to work between native props, and flexible props and settled currying a getAt() and putAt() methods to make this work and feel uniform 

project is here [https://github.com/woodmawa/GroovyV4sample] 

 

Wills expando is here [https://github.com/woodmawa/GroovyV4sample/tree/master/src/main/groovy/MOP]

tests are are [https://github.com/woodmawa/GroovyV4sample/blob/master/src/test/groovy/extensible/WillsExpandoTest.groovy] 

doing this with groovy v4 but not thing special and should work fine in groovy v3.  I did use @Compile static after i'd built the class, so it whilst not the most performant engineering provides the methods, and results I think you would want from a symmetric feel MOP experience 

might be some bloopers in here but hopefully you can see the idea.  

you don't have to know the static methods in advance - you can just query for them at run time.  

metaClass.static is so confusing and i dont really really understand what the standard code base is doing, i've implemented it here as internal class to wrap the staticMthods/staticProps maps 

This was easier for me to digest and work with - hope this helps 

couple of example methods here 

 
----
 

//non static form as we know the call instance context here
List<MetaMethod> getStaticMetaMethods () {

List<MetaMethod> mms = this.metaClass.getMethods().findResults\{Modifier.isStatic (it.modifiers) ? it : null}.collect()

List<MetaMethod> closureMetaMethodList =[]
for (entry in staticExpandoMethods) {
closureMetaMethodList.add (new ClosureStaticMetaMethod((String) entry.key, this.getClass(), (Closure) entry.value ) )
}

mms.addAll(closureMetaMethodList)
mms
}

and 

 

List<MetaProperty> getMetaProperties () {
List<MetaProperty> mps = metaClass.properties

// have to stop recursion on properties, and skip dynamic concurrent maps from showing
List<MetaProperty> expandoMetaProperties = []
CachedMethod cacheGet, cacheSet
MetaMethod metaGetter, metaSetter

for (expandoProp in expandoProperties) {
String name = expandoProp.key

/**
* to make this work - get two closures, from real methods that take take the dynamic propertyName as key, and will
* access the expando's propertyMap.
* Then curry the dynamicProperty name on that closure so it takes the same number of params as an ordinary property would
* create CachedMethods for the ::call() action
*/
Closure getterClos = this::getAt.curry(name)
Closure setterClos = this::putAt.curry( name)

cacheGet = new CachedMethod (getterClos.getClass().getMethod( 'call'))
cacheSet = new CachedMethod (setterClos.getClass().getMethod ('call', Object))

metaGetter = new ClosureMetaMethod ('getAt', this.getClass(), getterClos, cacheGet)
metaSetter = new ClosureMetaMethod ('getAt', this.getClass(), setterClos, cacheSet)
MetaBeanProperty mbp = new MetaBeanProperty (name, this.getClass(), metaGetter, metaSetter)
expandoMetaProperties.add (mbp)
}

mps.addAll (expandoMetaProperties)
mps
}

 

 

 

 

 

 

 

 


was (Author: woodmawa):
ok - this is not perfect by any means - but i've created a WillsExpando that offers what i feel would be relatively symetric logical behaviour 

 

it separates the extension props/methods  and statics props methods into maps - and then implements getProperty() getMethod() to intercept calls and provides propertyMissing etc to add these into the right map.

 

Had  fiddle trying to make the getMetaProperties () to work between native props, and flexible props and settled currying a getAt() and putAt() methods to make this work and feel uniform 

project is here [https://github.com/woodmawa/GroovyV4sample] 

 

Wills expando is here [https://github.com/woodmawa/GroovyV4sample/tree/master/src/main/groovy/MOP]

tests are are [https://github.com/woodmawa/GroovyV4sample/blob/master/src/test/groovy/extensible/WillsExpandoTest.groovy] 

doing this with groovy v4 but not thing special and should work fine in groovy v3.  I did use @Compile static after i'd built the class, so it whilst not the most performant engineering provides the methods, and results I think you would want from a symmetric feel MOP experience 

might be some bloopers in here but hopefully you can see the idea.  

you don't have to know the static methods in advance - you can just query for them at run time.  

metaClass.static is so confusing and i dont really really understand what the standard code base is doing, i've implemented it here as internal class to wrap the staticMthods/staticProps maps 

This was easier for me to digest and work with - hope this helps 

 

 

 

 

 

 

 

 

 

> Inconsistent metaClass capability for .static properties and methods vs ordinary dynamic properties and methods  
> -----------------------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-10392
>                 URL: https://issues.apache.org/jira/browse/GROOVY-10392
>             Project: Groovy
>          Issue Type: Improvement
>          Components: Compiler
>    Affects Versions: 3.0.9, 4.0.0-beta-2
>            Reporter: William Woodman
>            Priority: Minor
>             Fix For: 3.x, 4.x
>
>
> runtime addition and working with static dynamic properties and methods is inconsistent and doesnt work the same as the equivalent capability for ordinary dynamic properties and methods.
> I've tried to show the problem in the script code below 
> {code:groovy}
> package script
> class SomeClass {
> static String classDeclaredStatName = "in class definition static name"
> String name = "instance level name"
> }
> //add a new property to metaclass - works fine
> SomeClass.metaClass.dynProp = "dynamic property added"
> SomeClass.metaClass.dynMethod = \{"dynamic method added as closure"}
> SomeClass.metaClass.static.dynStaticProp = "dynamic static property added"
> SomeClass.metaClass.static.dynStaticMethod = \{"dynamic static method added"}
> assert SomeClass.classDeclaredStatName == "in class definition static name"
> assert SomeClass.dynStaticMethod() == "dynamic static method added"
> //this forces conversion of metaClassImpl to expandoMetaClass
> SomeClass myc = new SomeClass()
> assert myc.name == "instance level name"
> assert myc.classDeclaredStatName == "in class definition static name"
> assert myc.dynProp == "dynamic property added"
> assert myc.dynMethod() == "dynamic method added as closure"
> assert myc.dynStaticMethod() == "dynamic static method added"
> def res
> res = myc.metaClass.properties //returns list of metaBeanProperty
> res = myc.metaClass.getMetaMethods() //works and returns list of metaMethods
> //This is the only method for static's in MOP - this works but you have to know the name of the method in advance
> res = myc.metaClass.getStaticMetaMethod("dynStaticMethod", [] as ArrayList)
> //these functions are missing from MOP and would enable you to query for static props/methods 
> res = myc.metaClass.getStaticMetaMethods()     //this method doesnt exist in MOP api
> res = myc.metaClass.getStaticProperties()           //this method doesnt exist in MOP api either
> {code}



--
This message was sent by Atlassian Jira
(v8.20.1#820001)