Groovy探索之方法调用的动态性
????????????????????? Groovy探索之方法调用的动态性
?
?
在我以前的文字中,我一再强调,Groovy语言的方法也和Java语言的方法一样,是要依赖于类和对象的,因此,方法不能被单独作为对象传递和循环。同时,在《Groovy探索之闭包 八》中,我们提出来一个能让方法进行传递和循环的一个替代方案,这就是使用闭包来代替方法。 其实,Groovy语言的方法虽然也依赖于类和对象,但却并不妨碍Groovy语言的方法调用的动态性,也使得Groovy语言在方法的调用上与Java语言的不同特点,这就是我们这篇文字所要谈到的内容。 当然,Groovy语言的方法调用的动态性要归功于Gstring的动态性。下面试着举出一些简单的例子来说明。 比如说,我们有一只可爱的小狗,它有一些可爱的动作,现模拟如下:
?
?
?
class Dog { ??? def bark() { ?????? println 'woof!' ??? } ??? ??? def sit() { ?????? println 'sitting!' ??? } ??? ??? def jump() { ?????? println 'boing!' ??? } ??? }
?
现在,我们可以让它依次做上述的三个动作了:
?
??? ? ??? ? def dog = new Dog() ??? ? ??? ? def acts = ['sit','jump','bark'] ??? ? ??? ? acts.each{ ?????? ? dog."${it}"() ??? ? } ? 运行的结果为: sitting! boing! woof!
?
你会说啊,这基本上可以说是实现了命令模式了,不知道它的扩展性怎么样?我们现在可以试着让小狗多会一些动作了:
?
?
class Dog1 extends Dog { ??? def run() ??? { ?????? println 'running...' ??? } }
?
看看小狗会了这个动作没有?
?
?
?????? def dog = new Dog1() ?????? ?????? def actions = ['sit','bark','run'] ?????? ?????? actions.each{ ?????????? dog."${it}"() ?????? } ? 运行结果为: sitting! boing! woof! running...
?
不错啊,也有很好的扩展性。方法的动态性还有一个重要的内容就是要传递方法,这在Groovy语言中也可以通过传递对象来实现。请看下面的例子。 还记得我们在《Groovy探索之闭包 八》中对一盏灯的控制吗?我们有一个开灯的动作,如下:
?
class LightOn { ??? def doing() ??? { ?????? println 'Ligth turning on...' ??? } }
?
?
当然,我们也有一个关灯的动作:
?
class LightOff { ??? def doing() ??? { ?????? println 'Ligth turning off...' ??? } }
?
我们有一个开关,要控制这盏灯,它本身不能控制灯,而是由传入的动作决定的,如下:
?
?
class Switch { ??? def control(action) ??? { ?????? action."doing"() ??? } }
?
?
下面,我们就可以把开关灯的一些动作传递给Switch类的方法了:
?
??? ? ??? ? def sh = new Switch() ??? ? ??? ? sh.control(new LightOn()) ? 运行结果为: Ligth turning on...
?
这个实现就跟Java语言对于命令模式的实现很相似了,只是少了接口。原因是我们在Groovy语言中只要约定所有类的方法名都一样,我们就可以在客户端里使用“对象.方法名()”的形式调用该方法。而不同的动作则是通过对象的不同来区分的,这点跟Java语言很相似。只是在Groovy语言中有了“对象.方法名()”形式的方法调用,就可以不使用接口而调用方法了。
?
通过这样一种方法调用的动态性,我们就可以实现Java语言中的很多中模式了,比如命令模式和策略模式等等。
?
再次总结一下上面的Groovy语言的方法调用的动态性的实现,在Groovy语言中,我们可以使用两种方式变相实现方法调用的动态性:一是利用Gstring的动态性,固定类和对象,将方法名作为对象进行循环和传递,再利用“对象.方法名()”来实现方法的动态调用;二是固定方法名,以不同的类和对象来代表不同的动作,然后循环和传递对象,利用“对象.方法名()”来实现方法的动态调用。 两者都是最终要通过“对象.方法名()”来实现方法的动态调用的。那么有人要问了,如果我们的方法有参数的话,该怎么使用呢? 下面试着举出一个例子来说明这个问题,同时作为本篇的结束。
?
class Tools { ??? def max(int i1,int i2) ??? { ?????? Math.max(i1,i2) ??? } }
?
下面,我们来使用这个Tools类: ??? ? ??? ? def arg = [1,2] ??? ? ??? ? def tools = new Tools() ??? ? ??? ? println tools."max"(*arg) ?
?
可以看到,我们将参数按照先后顺序放在一个List对象里,然后再将该对象传给如下的这种形式: 对象.方法名(*List对象)
?
上面代码的运行结果为: 2 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |