【问题标题】:What is the static version of propertyMissing method in Groovy?Groovy 中 propertyMissing 方法的静态版本是什么?
【发布时间】:2019-01-26 00:17:35
【问题描述】:

好的 - 尝试查看/阅读,但不确定我是否对此有答案。

我有一个实用程序类,它在内部包装了一个静态 ConcurrentLinkedQueue。

实用程序类本身添加了一些静态方法 - 我不希望调用 new 来创建实用程序的实例。

我想拦截 getProperty 调用实用程序类 - 并在类定义中内部实现这些

在我使用它之前,我可以通过在实用程序类元类中添加以下内容来实现这一点

UnitOfMeasure.metaClass.static.propertyMissing = {name -> println "accessed prop called $name"}

println UnitOfMeasure.'Each'

但是我想做的是在类定义本身中声明拦截。我在类定义中尝试过这个 - 但它似乎从未被调用

static def propertyMissing (receiver, String propName) {
    println "prop $propName, saught"
}

我也试过了

static def getProperty (String prop) { println "accessed $prop"}

但这也不叫。

所以除了在我使用之前在我的代码/脚本中添加元类之外,如何在想要捕获属性访问的实用程序类中声明

我目前的实际课程是这样的

class UnitOfMeasure {
    static ConcurrentLinkedQueue UoMList = new ConcurrentLinkedQueue(["Each", "Per Month", "Days", "Months", "Years", "Hours", "Minutes", "Seconds" ])

    String uom

    UnitOfMeasure () {
        if (!UoMList.contains(this) )
            UoMList << this
    }

    static list () {
        UoMList.toArray()
    }

    static getAt (index) {
        def value = null
        if (index in 0..(UoMList.size() -1))
            value = UoMList[index]
        else if (index instanceof String) {
            Closure matchClosure = {it.toUpperCase().contains(index.toUpperCase())}
            def position = UoMList.findIndexOf (matchClosure)
            if (position != -1)
                value = UoMList[position]
        }
        value
    }

     static def propertyMissing (receiver, String propName) {
        println "prop $propName, saught"
    }


    //expects either a String or your own closure, with String will do case insensitive find
    static find (match) {
        Closure matchClosure
        if (match instanceof Closure)
            matchClosure = match
        if (match instanceof String) {
            matchClosure = {it.toUpperCase().contains(match.toUpperCase())}
        }
        def inlist = UoMList.find (matchClosure)
    }

    static findWithIndex (match) {
        Closure matchClosure
        if (match instanceof Closure)
            matchClosure = match
        else if (match instanceof String) {
            matchClosure = {it.toUpperCase().contains(match.toUpperCase())}
        }
        def position = UoMList.findIndexOf (matchClosure)
        position != -1  ? [UoMList[position], position] : ["Not In List", -1]
    }
}

我很欣赏为静态实用程序类而不是实例级属性拦截执行此操作的秘诀,并在类声明中执行此操作 - 而不是在我进行调用之前添加到 metaClass。

只是为了让您可以看到实际的类和调用的脚本 - 我在下面附上了这些

调用该类的脚本如下所示

println UnitOfMeasure.list()

def (uom, position) = UnitOfMeasure.findWithIndex ("Day")
println "$uom at postition $position"

// works UnitOfMeasure.metaClass.static.propertyMissing = {name -> println "accessed prop called $name"}
println UnitOfMeasure[4]
println UnitOfMeasure.'Per' 

像这样的错误

[Each, Per Month, Days, Months, Years, Hours, Minutes, Seconds]
Days at postition 2
Years
Caught: groovy.lang.MissingPropertyException: No such property: Per for class: com.softwood.portfolio.UnitOfMeasure
Possible solutions: uom
groovy.lang.MissingPropertyException: No such property: Per for class: com.softwood.portfolio.UnitOfMeasure
Possible solutions: uom
    at com.softwood.scripts.UoMTest.run(UoMTest.groovy:12)

【问题讨论】:

    标签: groovy interception mop


    【解决方案1】:

    propertyMissing方法的静态版本被称为$static_propertyMissing

    static def $static_propertyMissing(String name) {
        // do something
    }
    

    这个方法被MetaClassImpl at line 1002调用:

    protected static final String STATIC_METHOD_MISSING = "$static_methodMissing";
    protected static final String STATIC_PROPERTY_MISSING = "$static_propertyMissing";
    
    // ...
    
    protected Object invokeStaticMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
        MetaClass mc = instance instanceof Class ? registry.getMetaClass((Class) instance) : this;
        if (isGetter) {
            MetaMethod propertyMissing = mc.getMetaMethod(STATIC_PROPERTY_MISSING, GETTER_MISSING_ARGS);
            if (propertyMissing != null) {
                return propertyMissing.invoke(instance, new Object[]{propertyName});
            }
        } else {
            // .....
        }
        // ....
    }
    

    例子:

    class Hello {
        static def $static_propertyMissing(String name) {
            println "Hello, $name!"
        }
    }
    
    Hello.World
    

    输出:

    Hello, World!
    

    【讨论】:

    • 天哪,你不必只爱堆栈溢出 - 绝对精彩。工作一种享受,我可以从这里拿走它。显然不是一个常见的用例,否则它会是一些书或其他或其他帖子。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2020-12-27
    • 2011-05-06
    • 1970-01-01
    • 2019-01-04
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    相关资源
    最近更新 更多