使用methodMissing和propertyMissing

使用methodMissing和propertyMissing

从1.5版本开始,Groovy支持“methodMissing(方法缺失)”的概念了,它和“invokeMethod(调用方法)”的区别在于它只能用于方法调用失败时。

以下介绍了这个行为的两个重要方面:

  1. 因为method/propertyMissing仅出现在方法调用失败时,所以它们的调用需要巨大的开销。
  2. 因为method/propertyMissing并不像invokeMethod那样拦截任何方法调用,所以在使用元编程时它会显得更高效。

使用methodMissing实现动态方法注册(dynamic method registration)

一般来说,当使用methodMissing的时候,代码会检查一遍Groovy的方法调用逻辑,并以某种方式使得下次相同方法的快速调用成为可能。 举一个GORM的动态查找器的例子。这是通过methodMissing实现的。它们是怎样工作的呢?代码类似于这样:

class GORM {
   def dynamicMethods = [...] // 一个使用正则表达式的动态方法的数组
   def methodMissing(String name, args) {
       def method = dynamicMethods.find { it.match(name) }
       if(method) {
          GORM.metaClass."$name" = { Object[] varArgs ->
             method.invoke(delegate, name, varArgs)
          }
          return method.invoke(delegate,name, args)
       }
       else throw new MissingMethodException(name, delegate, args)
   }
}

现在注意,如果我们发现一个可调用的方法,我们会在运行中使用ExpandoMetaClass(可扩展元类)动态地注册一个新方法。这就是为什么下次相同方法调用时会如此高效的原因。通过这个方式,methodMissing就不会有invokeMethod的额外开销,也不会在第二次调用中耗费大量开销了。

使用propertyMissing

Groovy也支持propertyMissing,它能尝试对缺失的属性进行处理。你可以用带有一个String参数的propertyMissing定义来实现一个获取器(getter):

class Foo {
   def propertyMissing(String name) { name }
}
def f = new Foo()
 
assertEquals "boo", f.boo

你可以添加带有一个value参数的第二个propertyMissing定义来实现一个设置器(setter):

class Foo {
   def storage = [:]
   def propertyMissing(String name, value) { storage[name] = value }
   def propertyMissing(String name) { storage[name] }
}
def f = new Foo()
f.foo = "bar"
 
assertEquals "bar", f.foo

就像使用methodMissing那样,你也许会在运行时动态注册新属性以提升代码的性能。

静态方法和属性

通过ExpandoMetaClass(可扩展元类),你可以添加methodMissing和propertyMissing来处理静态方法和属性。

 
wiki/user_guide/using_methodmissing_and_propertymissing.txt · 最后更改: 2008-09-23 23:29 由 johnny
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki