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

Groovy探索之MOP 五 针对接口类型的动态性

发布时间:2020-12-14 17:09:02 所属栏目:大数据 来源:网络整理
导读:Groovy探索之MOP 五 针对接口类型的动态性 ? ? 这里所说的接口类型,在Java语言和Groovy语言中,当然是既包括了基类类型和接口。所谓"接口类型的动态性",指的是在运行期内给基类或接口动态的添加方法,使得基类以及它的子类、接口的实现,都能访问这些方法

Groovy探索之MOP 五 针对接口类型的动态性

?

?

这里所说的接口类型,在Java语言和Groovy语言中,当然是既包括了基类类型和接口。所谓"接口类型的动态性",指的是在运行期内给基类或接口动态的添加方法,使得基类以及它的子类、接口的实现,都能访问这些方法。

这个功能一向是我比较感兴趣的一个功能。因为我们在编程的实践中,会使用各种各样的应用API,还有JDK,在使用它们的过程中,可能有一些接口及它们的子类我们会经常使用到,但是在使用的过程中,我们又感到非常的不方便。这时候,我们可以使用Categories机制来对我们所使用的类进行扩充功能,但如果一个类有很几个子类或者一个接口有好几个实现,对于所有的子类或实现,我们都希望进行相同的功能扩充。那么,如果我们使用Categories机制的话,我们就不得不对所有的子类或实现进行依次扩充。这就造成了重复性的劳动。

而我们使用ExpandoMetaClass机制的话,则只需要对基类或者接口进行功能扩充,那么所有的子类或实现都能够得到该功能。这是多么的激动人心啊!

首先,我们来看一个基类和它的子类的例子。

我们已经拥有了如下的一个基类:

?

class A

{

??? def afuction()

??? {

?????? println 'a'

??? }

}

?

?

同时,我们也已经有了好几个它的子类,下面就是一个例子:

?

class B extends A

{

??? def bfuction()

??? {

?????? println 'b'

??? }

}

?

?

?

现在,我们希望给A类在运行期内增加一个方法,同时,B类也拥有了该方法。

首先,使得ExpandoMetaClass enabled globally:

?

??? ? ExpandoMetaClass.enableGlobally()

?

接着,我们给A类增加方法:

?

??? ? A.metaClass."aAndb" = {

?????????? ? ->

?????????? ? ? println 'a and b'

??? ? }

?

?

下面,我们就可以测试了:

?

??? ? def a = new A()

??? ?

??? ? a.aAndb()

??? ?

??? ? def b = new B()

??? ?

??? ? b.aAndb()

?

?

运行结果为:

a and b

a and b

?

?

果然达到了我们的要求。一切都很简单,但需要注意的是在给基类添加方法之前,一定要加上"ExpandoMetaClass.enableGlobally()",否则,就会报告如下的错误:

Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: mop.B.aAndb() is applicable for argument types: () values: {}

??? at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:54)

??? at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:59)

??? at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:169)

at mop.A.invokeMethod(Testor3.groovy)

?

?

同样,我们也可以对一个接口的所有的实现进行功能扩展。比如,我们想对List接口进行功能扩展,举一个简单的例子--我们想获取一个List对象的倒序List对象,就可以进行如下的编程:

?

?

??? ? ExpandoMetaClass.enableGlobally()

??? ?

??? ? List.metaClass.reversed = {

?????????? ? ->

?????????? ? ? def rl = []

?????????? ? ? for(int i in (delegate.size()-1..0))

?????????? ? ? {

?????????? ? ????? rl << delegate.getAt(i)

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

?????????? ? ? rl

??? ? }

?

?

跟基类的原理一样,我们是在接口上添加功能。下面我们就可以进行测试了:

?

??? ? def list = [1,2,3]

??? ?

??? ? list = list.reversed()

??? ?

??? ? println list

??? ?

?

?

运行的结果为:

[3,1]

?

?

一切也都显得比较简单,唯一需要注意的是,记得加上如下的语句:

?

ExpandoMetaClass.enableGlobally()

?

否则,同样会报"MissingMethodException"的错误。

(编辑:李大同)

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

    推荐文章
      热点阅读