Groovy - 探索之 invokeMethod 方法

简介: Groovy - 探索之 invokeMethod 方法


我们知道,在Java语言中,所有的Java类都继承了Object对象。通过Object对象,所有的Java类都隐藏的实现了“equals”等方法。同样,在Groovy语言中,所有的Groovy类都隐藏的实现了GroovyObject接口,这样,我们的Groovy类就隐藏的实现了很多的方法,如“isCase”等。

这篇文字要谈谈的就是GroovyObject接口的“invokeMethod”方法,这个方法对于我们Groovy语言的动态性编程很有帮助,可以帮助我们实现一些很有时代性的功能,比如DSL。本文就是要谈谈“invokeMethod”方法的基础,通过这个基础,我们才可以通向DSL编程。

首先,我们来看看“invokeMethod”方法在一个Groovy类中的作用,先来看一个例子:

classInvokeMethodTestor {
deftest()
    {
println'hello,function name is test'    }
definvokeMethod(Stringname,Objectargs)
    {
println"the other function, name is ${name}"    }
}

这是一个很简单的Groovy类,我们有一个test方法,用来向控制台打印一句话;然后我们实现了invokeMethod方法,并且把参数“name”打印在控制台。

在讲述“invokeMethod”方法的作用之前,我们先来测试一下上面的类。

deftestor=newInvokeMethodTestor()
testor.test()
testor.hello()
testor.doSomething()

我们先来看看测试结果:

hello,function name is test

the other function, name is hello

the other function, name is doSomething

通过测试结果,我们可以看出,语句“testor.test()”调用了“InvokeMethodTestor”类的“test”方法,而语句“testor.hello()”和“testor.doSomething()”却都调用了“InvokeMethodTestor”类的“invokeMethod”方法。

这就告诉我们,对于一个实现了“invokeMethod”方法的Groovy类的对象,可以执行任意的方法,如果该方法已经在该类中实现,就调用该方法,如“testor.test()”就调用“InvokeMethodTestor”类的“test”方法;如果该方法没有在该类中实现,如“testor.hello()”和“testor.doSomething()”,就调用该类的“invokeMethod”方法。

这样说来,“invokeMethod”方法其实蛮简单的,一点都不神秘和麻烦。但是它的作用却一点都不能小觑,它给我们的Groovy语言编程带来了很大的动态性。

下面试着举一个小小的例子说明。

比如,我们有一个Student类,里面放的是学生的成绩,如“语文”、“数学”、“英语”等等,如下:

classStudent {  
Stringno;
Stringname;
floatchinScore;
floatmathScore;
floatenglScore;
floatphysScore;
floatchemScore;
floattotalScore;
}

同时,我们有一些学生(已经记录的各科成绩)在一个List对象里,如下:

Listscores= [newStudent(no:'123',name:'Tom',chinScore:90,mathScore:99,englScore:60,physScore:88,chemScore:96)]
scores<<newStudent(no:'124',name:'Mike',chinScore:88,mathScore:90,englScore:90,physScore:98,chemScore:87)
scores<<newStudent(no:'125',name:'Alice',chinScore:100,mathScore:55,englScore:98,physScore:67,chemScore:56)

这些学生在List对象里是以学号排序的,我们来看看:

1. scores.each{
2.     println it.name+' : '+it.no
3. }

结果为:

Tom : 123

Mike : 124

Alice : 125

可以看到的确如此。

下面,我们的语文老师希望以语文成绩排序,而数学老婆希望以数学成绩排序,英语老师则希望以英语成绩排序,……,班主任则希望以总分排序。

看到这里,你可以会说,我做一个方法来实现所有老师的愿望,这个方法有两个参数,一个是List对象,一个是type,type参数用来表示语文老师要的语文,数学老师要的数学等等。

这个方法当然是不错的,但不是最酷的。最酷的方法是语文老师调用sortByChinScore()方法,而数学老师调用sortByMathScore()方法,英语老师调用sortByEnglScore()方法,等等。

且慢!这不是要我写六七个方法来实现所有老师的要求?这未免有点无聊吧?像这样的代码写起来也枯燥乏味呀。

当然不用写六七个方法,答案就是“invokeMethod”方法。我们来看看是如何实现这样一个想法的:

importjava.util.Collectionsimportjava.util.ComparatorclassSortHelper{
deflistpublicSortHelper(list)
    {
this.list=list    }
// 所有的以sort开头的方法都来调用“invokeMethod”,当然,其他方法也有可能来调用它,但我不做处理。definvokeMethod(Stringname,Objectargs)
    {
//首先判断方法名是否以“sortBy”开头,是则处理,否则不处理。if(name.indexOf('sortBy')==0)
       {
//取得属性名,如“ChinScore”name=name[6..name.length()-1]
//把第一个字母由大写变小写,就取得了属性名name=name[0].toLowerCase()+name[1..name.length()-1]
//实现Comparator接口,大家可以参考jdk文档。defcomparator= {
node1,node2->returnnode1."${name}".compareTo(node2."${name}")
           } asComparator//排序Collections.sort(this.list,comparator) 
       }
    }
}

真的很简单。下面我们来测试一些这个类:

defsorter=newSortHelper(scores)
sorter.sortByChinScore()
scores.each{
printlnit.name}

结果为:

Mike

Tom

Alice

从语文成绩来看,Mike 88,Tom 90,Alice 100。排序是正确的。下面我们以数学成绩排序:

1. sorter.sortByMathScore()
2.  scores.each{
3.    println it.name
4. }

结果为:

Alice

Mike

Tom

从数学成绩来看,Alice 55,Mike 90,Tom 99,排序也没有问题。大家可以再测几个看看。

像这样的功能的确够酷,我们今后在Groovy/Grails平台会经常遇到;同时,这样一个思想也可以发展成DSL的一种实现。

目录
相关文章
|
消息中间件 存储 Java
Kotlin中正确的使用Handler
如果`Handler`在`Activity`中是以非静态内部类的方式初始化的,那么`Handler`默认就会持有`Activity`的实例,因为在`Java`中:**非静态内部类默认会持有外部类的实例,而静态内部类不会持有外部类的实例**
322 0
【错误记录】Groovy 函数参数动态类型报错 ( Caught: groovy.lang.MissingMethodException: No signature of method )
【错误记录】Groovy 函数参数动态类型报错 ( Caught: groovy.lang.MissingMethodException: No signature of method )
2440 0
【错误记录】Groovy 函数参数动态类型报错 ( Caught: groovy.lang.MissingMethodException: No signature of method )
|
XML 敏捷开发 IDE
Groovy 的介绍和简单的使用
Groovy 的介绍和简单的使用
Groovy - 探索之 MOP(invokeMethod 和 methodMissing 方法)
Groovy - 探索之 MOP(invokeMethod 和 methodMissing 方法)
138 0
Groovy - Groovy ambiguous method overload
Groovy - Groovy ambiguous method overload
571 0
|
Java
【Groovy】Groovy 脚本调用 ( Java 类中调用 Groovy 脚本 )
【Groovy】Groovy 脚本调用 ( Java 类中调用 Groovy 脚本 )
601 0
|
Java
【Groovy】Groovy 扩展方法 ( Groovy 扩展方法引入 | 分析 Groovy 中 Thread 类的 start 扩展方法 )
【Groovy】Groovy 扩展方法 ( Groovy 扩展方法引入 | 分析 Groovy 中 Thread 类的 start 扩展方法 )
247 0
【错误记录】Groovy 函数拦截调用 invokeMethod 导致栈溢出 ( java.lang.StackOverflowError )
【错误记录】Groovy 函数拦截调用 invokeMethod 导致栈溢出 ( java.lang.StackOverflowError )
189 0
【错误记录】Groovy 函数拦截调用 invokeMethod 导致栈溢出 ( java.lang.StackOverflowError )