Jochen,

> On 8. 1. 2024, at 16:10, Jochen Theodorou <blackd...@gmx.org> wrote:
> I would like to know from users on this list mostly if they are using
> specific features of the meta class system and MOP, but especially what for.
> 
> (1) categories
> ...
> use (CategoryClass) {
>  // some code and callstack here influenced by CategoryClass
> }
> I am especially interested in knowing if you try to add a method to code that 
> is not part if the use-block here.

All the time, mostly to extend library classes, occasionally to split my own 
class implementation to more source files. I never ever use the use-block.

My aim here is to have something as close to the Objective-C categories as 
possible. Not entirely successful (the worst problem is that the Groovy 
category-based extensions do not work properly through introspection, whilst 
methods added by an ObjC category are real first-class citizens, not 
distinguishable from the “normal” ones), but I am reasonably close and the 
support is immensely useable to me.

For convenience, I did my own Extension ASTT closely based on the Alex 
Tkachman's Category, but improved a bit, so that
- inside of my @Extension(String) class MyStringExtensions { ... }, I can put 
both instance and static extension methods, and for the latter, my ASTT 
automatically creates an appropriate static extension class;
- the extension class list is collected compile-time and (eventually when my 
build script creates the application) automatically added to the 
org.codehaus.groovy.runtime.ExtensionModule manifest, so that they just-work 
without any extra ado.

> (2) per instance meta classes
> https://groovy-lang.org/metaprogramming.html#_per_instance_metaclass
> shows examples here
> Anyone using that?

Can't recall I ever needed that.

> (3) Custom meta class
> Anyway trying to force the usage of something else then MetaClassImpl
> for the meta class?

Well sort of, though a pretty trivial one. My goal is to get rid of NPEs; in my 
personal opinion that darned thing is a proper disaster and the right behaviour 
is a completely consistent null-propagation (essentially what Groovy calls a 
“safe dispatch”). Among many other things, what I do is

===
        def mc=new OCSNMC(org.codehaus.groovy.runtime.NullObject)
        mc.initialize()
        org.codehaus.groovy.runtime.NullObject.metaClass=mc
... ...
}
class OCSNMC extends DelegatingMetaClass {
    OCSNMC(Class clazz){
        super(clazz)
    }
    Object invokeMethod(Object object, String methodName, Object[] arguments) {
        if (arguments.size()==1 && methodName=='is') return arguments[0]==null
        if (arguments.size()==0 && methodName=='iterator') return [].iterator()
        if (arguments.size()==0 && methodName=='hasZeroValue') return YES
        null
    }
    // alas, does not seem to work for getProperty; that one must be supported 
by ASTTs
}
===

Aside that, not sure if interesting to you, but I install my own methods into 
metaclasses all the time, like e.g.,

===
        NSMutableDictionary.metaClass.putAt<<{ key,value ->
            if (value==nil) delegate.removeObjectForKey(key)
            else delegate.setObjectForKey(value,key)
        }
        ...
        NSKeyValueCoding.NullValue.class.metaClass.asBoolean={ -> false }
===

and I even (of course having done ExpandoMetaClass.enableGlobally()) install 
global handlers

===
        // for some triple-weird reason simply defining propertyMissing in an 
extension does NOT work (never gets called)
        Object.metaClass.propertyMissing={name->
            DPA.propertyMissing(delegate,name)
        }
        Object.metaClass.static.propertyMissing={name->
            DPA.staticPropertyMissing(delegate,name)
        }
===

DPA is my own rather non-trivial class, whose code dynamically fixes properties 
of library classes, i.e., allows me to write SomeLibraryClassOrInstance.foo for 
classes which have either static or instance method foo() and if so happens, 
getFoo() { foo() } (essentially) is installed automatically to the metaclass 
(the rationale here is that the WebObjects standard, which long long predates 
the unlucky Java one, has setters setFoo(foo) and getters foo(), not getFoo()).

Thanks and all the best,
OC


Reply via email to