加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Groovy探索之MOP 十五 方法名的动态性(2)

发布时间:2020-12-14 17:08:05 所属栏目:大数据 来源:网络整理
导读:? ??????????????? Groovy 探索之 MOP 十五 ? 方法名的动态性( 2 ) ? ? ? ? ??? ? List scores = [ new Student(no: '123' ,name: 'Tom' ,chinScore: 90 ,mathScore: 99 ,englScore: 60 ,physScore: 88 ,chemScore: 96 )] ??? ? scores new Student(no: '1

?

??????????????? Groovy探索之MOP 十五? 方法名的动态性(2

?

?

?

?

??? ? 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)

?

??? ? def sorter = new SortHelper(scores)

??? ? sorter.sortByChinScore()

??? ?

??? ? scores.each{

?????? ? println it.name

??? ? }

?

???

?

?

运行结果为:

Mike

Tom

Alice

?

?

我们都记得我们的初中数学里学过的对数的概念:对数里面有一个底的概念,比如我们在程序里把以2为底的对数写成如下的样子:

log28

即以2为底8的对数,这样,我们可以以任何一个自然数为底,但我们最常用的是以10为底的对数,即:

log10100

10为底的对数,我们通常写成:

lg100

?

问题为:我们在某种情况下,可能会计算以1100之间的任何一个数为底的对数。按照上面的分析,其实,就是我们需要给某个工具类100个计算对数的方法。

这就是方法名的动态性的使用了。

我们还是先给出这个工具类来:

?

class Util

{

???

}

?

?

?

这个工具类什么也都没有实现,留给我们在运行期内动态添加方法,如下:

?

??? ? (1..101).each{

?????? ? int base->

?????????? ? Util.metaClass.'static'."log$base" = {

????????????????? ? int n -> Math.log(n) / Math.log(base)

?????????? ? }

??? ? }

?

?

它是把1100进行遍历,产生了一百个方法,至于如何计算各个底的对数的方法,那是数学公式的问题,我们在这里不再详述。

有了上面的代码,我们现在就可以写测试代码了:

?

??? ? println Util.log20(400)

??? ?

??? ? println Util.log100(100)

???

?

运行结果为:

2.0

1.0

?

?

?

现在,我们可以看到,我们的这些对数方法是不是写得很漂亮?

?

Groovy语言中,动态委派技术永远是我们最感兴趣的技术。而这种动态委派技术的实现,其实也需要用到我们使用ExpandoMetaClass类来实现的动态方法名。

下面就来说一说如何实现动态委派技术。

这是一个简单的委派类:

class Delegator {

???

??? ?private targetClass

??? ?

??? ?private delegate

??? ?

??? ?Delegator(targetClass,delegate) {

?????? ?

?????? ?this.targetClass = targetClass

?????? ?

?????? ?this.delegate = delegate

??? ?

??? ?}

??? ?

??? ?def delegate(String methodName) {

?????? ?

?????? ?delegate(methodName,methodName)

?????? ?

??? ?}

??? ?

??? ?def delegate(String methodName,String asMethodName) {

?????? ?

?????? ?targetClass.metaClass."$asMethodName" = delegate.&"$methodName"

?????? ?

??? ?}

??? ?

??? ?}

?

?

?

这个类十分的简单,可以明显的看到“delegate(String methodName,String asMethodName)”方法就是使用的ExpandoMetaClass类实现的动态方法名,如下:

?

targetClass.metaClass."$asMethodName" = delegate.&"$methodName"

?

现在,我们就来使用这个动态委派技术。

下面,我们有一个A类:

public class A{

?

??? def a()

??? {

?????? println 'invoke a function...'

??? }

???

}

?

?

它就是我们需要委派的原始类。下面是一个简单的B类,没有任何的方法:

public class B{

?

}

?

?

下面就可以写测试代码了:

?

?????? def a = new A()

??????

?????? def delegator = new Delegator(B,a)

??????

?????? delegator.delegate 'a'

??????

?????? delegator.delegate 'a','b'

??????

?????? delegator.delegate 'a','c'

??????

?????? def b = new B()

??? ???

?????? b.a()

??????

?????? b.b()

??????

?????? b.c()

???

?

在上面的代码中,我们分别把A类的“a”方法委派给了B类的三个方法:“a”、“b”和“c”方法。

最后,我们在B类对象中调用这三个方法。运行结果为:

invoke a function...

invoke a function...

invoke a function...

?

?

这充分的体现了使用的ExpandoMetaClass类实现的方法名的动态性的特点。

值得注意的是,上面的动态委派技术的实现,需要在我们的Groovy1.5及以上的版本中才能正常编译。可以确定的是,Groovy1.0版本是不能编译的。

同时需要说明的是,我的所有文字,除非注明需要Groovy1.5及以上版本,否则都可以在Groovy1.0版本及以上编译运行。

谢谢!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读