Groovy探索之MOP 十五 方法名的动态性(1)
???????? Groovy探索之MOP 十五? 方法名的动态性(1) ? ? ? 到目前为止,我们的《Groovy探索之MOP》系列已经谈到了使用ExpandoMetaClass的方方面面,但值得注意的是,我们通过ExpandoMetaClass给一个类在运行期内添加一个方法,不管是普通方法还是静态方法,我们都是添加一个确定方法名的方法。即我们添加一个方法名为A的方法,然后才能使用这个方法A。 然而,方法名的动态性,其实是我们早已接触过的事情,比如在《Groovy探索之invokeMethod方法》里,我们就可以创建形如“sortByXxxxx()”这样漂亮的方法。当然了,在那篇文字里,我们是通过“invokeMethod”方法来实现的。 我们都知道,使用ExpandoMetaClass在运行期内给一个对象或类添加一个方法要比hook方法简单得多,所以,我们在实际的编码过程中,更多时候会用到ExpandoMetaClass来实现。那么,我们使用ExpandoMetaClass是否也可以实现上面hook方法所实现了的方法名的动态性呢? 我们知道,使用ExpandoMetaClass在运行期内添加一个方法(不管是给对象还是给类),形式都是像下面的样子: ? 类名.metaClass.方法名 = 方法体 ? 同时,上面的公式还可以写成如下的样子: ? ? 类名.metaClass. "方法名" = 方法体 ? 这下我们明白了,既然方法名可以用双引号括起来,那么,如果双引号里面是一个Gstring对象的话,这样,我们就可以给方法赋予一个可变的数据了。从而达到了我们使用ExpandoMetaClass实现方法名的动态性的目的了。 ? 废话少说,我们还是先来看一个例子吧! ? 现在,我们有一个T类,如下: ? class T { ??? } ? ? 我们就可以这样对T类添加方法: ? ??? ? String functionName = "a"; ??? ? ??? ? T.metaClass."$functionName" = { ?????????? ? println "invoke $functionName" ??? ? } ??? ? ??? ? def t = new T() ??? ? ??? ? t.a() ??? ? 我们在添加方法的时候,使用了一个Gstring对象来代替了写死的字符串,这样就实现了方法名的动态性。运行结果为: ? invoke a ? 当然了,你可能会觉得上面的方法名的动态性还不够清晰,那么,我们可以实现如下的一个静态方法,来达到我们方法名动态性的目的: ? ??? def static add(functionName) ??? { ?????? T.metaClass."$functionName" = { ????????????? ? println "invoke $functionName" ?????? ? } ??? } ??? ? 这样,我们就可以如下来使用它了: ? ??? ? add('b') ??? ? ??? ? def t1 = new T() ??? ? ??? ? t1.b() ??? ? ??? ? ??? ? add('c') ??? ? ??? ? def t2 = new T() ??? ? ??? ? t2.c() ??? ? 运行结果为: invoke b invoke c ? 上面的例子只是小儿科,我们使用ExpandoMetaClass实现的方法名的动态性同样可以使用于《Groovy探索之invokeMethod方法》中的那个有名的例子。关于那个例子的来历,大家可以在原文中看到,这里就不再重述。 在那篇文字中,Student类是这样的: class Student { ??? ??? String no; ??? String name; ??? float chinScore; ??? float mathScore; ??? float englScore; ??? float physScore; ??? float chemScore; ??? float totalScore; ? } ? ? 同样,我们的那个排序工具类还是保留,只是不再实现它的排序方法了,如下: ? class SortHelper { ? ??? def list ??? ??? public SortHelper(list) ??? { ?????? this.list = list ??? } ? } ? ? 当然,我们的排序方法是要留给ExpandoMetaClass来实现的,下面就是: ? ??? ? ['chinScore','mathScore','englScore','physScore','chemScore','totalScore'].each{ ?????? ? name -> ?????? ? ? def name1 = name[0].toUpperCase()+name[1..-1] ?????? ? ? SortHelper.metaClass."sortBy${name1}" = { ?????? ? ????? ->? ?????? ? ???????? def comparator = { ???????????????????????? node1,node2 -> ????????????????? ?????? return node1."${name}".compareTo(node2."${name}") ????????????????? } as Comparator ????????????????? ????????????????? Collections.sort(delegate.list,comparator) ?????? ? ? } ??? ? } ? ? ? 我们的想法就是,把要实现的方法的方法名(或部分)组成一个数组,然后依次遍历,交给ExpandoMetaClass来添加方法。 上面的代码都很简单,在这里我们就不再多说了。 最后,我们来写代码测试上面的添加方法了。如下: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |