Groovy探索之invokeMethod方法

                         Groovy探索之invokeMethod方法
 
我们知道,在Java语言中,所有的Java类都继承了Object对象。通过Object对象,所有的Java类都隐藏的实现了“equals”等方法。同样,在Groovy语言中,所有的Groovy类都隐藏的实现了GroovyObject接口,这样,我们的Groovy类就隐藏的实现了很多的方法,如“isCase”等。
这篇文字要谈谈的就是GroovyObject接口的“ invokeMethod”方法,这个方法对于我们Groovy语言的动态性编程很有帮助,可以帮助我们实现一些很有时代性的功能,比如DSL。本文就是要谈谈“ invokeMethod”方法的基础,通过这个基础,我们才可以通向DSL编程。
首先,我们来看看“ invokeMethod”方法在一个Groovy类中的作用,先来看一个例子:
class InvokeMethodTestor {
   
    def test ()
    {
       println 'hello,function name is test'
    }
   
    def invokeMethod(String name,Object args)
    {
       println "the other function, name is ${name}"
    }
 
}
 
这是一个很简单的 Groovy 类,我们有一个 test 方法,用来向控制台打印一句话;然后我们实现了 invokeMethod 方法,并且把参数“ name ”打印在控制台。
在讲述“ invokeMethod”方法的作用之前,我们先来测试一下上面的类。
def testor = new InvokeMethodTestor()
     
     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 类,里面放的是学生的成绩,如“语文”、“数学”、“英语”等等,如下:
class Student {
   
    String no;
    String name;
    float chinScore;
    float mathScore;
    float englScore;
    float physScore;
    float chemScore;
    float totalScore;
 
}
 
同时,我们有一些学生(已经记录的各科成绩)在一个 List 对象里,如下:
List scores = [ new Student(no: '123' ,name: 'Tom' ,chinScore: 90 ,mathScore: 99 ,englScore: 60 ,physScore: 88 ,chemScore: 96 )]
     scores<< new Student(no: '124' ,name: 'Mike' ,chinScore: 88 ,mathScore: 90 ,englScore: 90 ,physScore: 98 ,chemScore: 87 )
 scores<< new Student(no: '125' ,name: 'Alice' ,chinScore: 100 ,mathScore: 55 ,englScore: 98 ,physScore: 67 ,chemScore: 56 )
 
这些学生在 List 对象里是以学号排序的,我们来看看:
     scores. each {
         println it.name+ ' : ' +it.no
 }
 
结果为:
Tom : 123
Mike : 124
Alice : 125
 
可以看到的确如此。
下面,我们的语文老师希望以语文成绩排序,而数学老婆希望以数学成绩排序,英语老师则希望以英语成绩排序, …… ,班主任则希望以总分排序。
看到这里,你可以会说,我做一个方法来实现所有老师的愿望,这个方法有两个参数,一个是 List 对象,一个是 type type 参数用来表示语文老师要的语文,数学老师要的数学等等。
这个方法当然是不错的,但不是最酷的。最酷的方法是语文老师调用 sortByChinScore ()方法,而数学老师调用 sortByMathScore ()方法,英语老师调用 sortByEnglScore ()方法,等等。
且慢!这不是要我写六七个方法来实现所有老师的要求?这未免有点无聊吧?像这样的代码写起来也枯燥乏味呀。
当然不用写六七个方法,答案就是“ invokeMethod ”方法。我们来看看是如何实现这样一个想法的:
import java.util.Collections
import java.util.Comparator
 
class SortHelper{
   
    def list
   
    public SortHelper(list)
    {
       this .list = list
    }
   
// 所有的以 sort 开头的方法都来调用“ invokeMethod ”,当然,其他方法也有可能 // 来调用它,但我不做处理。
    def invokeMethod(String name,Object args)
    {
       // 首先判断方法名是否以“ sortBy ”开头,是则处理,否则不处理。
       if (name.indexOf( 'sortBy' )== 0 )
       {
          
           // 取得属性名,如“ ChinScore
           name = name[ 6 ..name.length()- 1 ]
          
           // 把第一个字母由大写变小写,就取得了属性名
           name = name[ 0 ].toLowerCase()+name[ 1 ..name.length()- 1 ]
          
           // 实现 Comparator 接口,大家可以参考 jdk 文档。
           def comparator = {
                  node1,node2 ->
                  return node1. "${name}" . compareTo (node2. "${name}" )
           } as Comparator
          
           // 排序
           Collections. sort ( this .list,comparator)
          
       }
    }
 
}
 
真的很简单。下面我们来测试一些这个类:
      def sorter = new SortHelper(scores)
     sorter.sortByChinScore()
     
     scores. each {
         println it.name
 }
 
结果为:
Mike
Tom
Alice
 
从语文成绩来看, Mike 88 Tom 90 Alice 100 。排序是正确的。下面我们以数学成绩排序:
 
     sorter.sortByMathScore()
     
     scores. each {
         println it.name
 }
 
结果为:
 
Alice
Mike
Tom
 
从数学成绩来看, Alice 55 Mike 90 Tom 99 ,排序也没有问题。大家可以再测几个看看。
像这样的功能的确够酷,我们今后在 Groovy/Grails 平台会经常遇到;同时,这样一个思想也可以发展成 DSL 的一种实现。
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值