Groovy探索之运算符的重载 二
前一篇详细的说了说算术运算符和关系运算符的重载,这篇要说说赋值运算符和取值运算符,即“.”运算符的重载。
还是以前一篇的Yuan类来作为例子。
class Yuan
{
def num
def toString()
{
this.num
}
}
有了上面的类的定义,我们就可以如下使用这个类:
def y = new Yuan()
y.num = 109
println y.toString()
其中,“y.num = 109”就是一个赋值语句,关键的运算符就是“.”;当然,我们还可以用该运算符进行取值运算,如下:
println y.num
我们今天要说的就是对“.”运算符的重载。当然,只要我们稍微一想,就可以知道,该运算符应该和“set”和“get”方法有关。不错,的确如此。
下面,我们来看看如何重载“.”运算符。
class Yuan
{
def num
def getOwner()
{
print 'tom'
}
def toString()
{
this.num
}
}
要重载取值运算,当然只要“get”方法就行了,注意看代码中的“getOwner()”方法,实现了它,我们就可以写出“y.owner”这样的代码来。
下面来看我们的测试代码:
def y = new Yuan(num:100)
y.owner
println " has ${y.toString()} yuan."
运行结果为:
tom has 100 yuan.
当然,重载赋值运算就和“set”方法相关了,如下:
class Yuan
{
def num
def setOwner(name)
{
println name
}
def toString()
{
this.num
}
}
测试代码如下:
def y = new Yuan(num:100)
y.owner = 'mike'
可以看到,“.”运算符的重载跟其他运算符的重载也都一样,没有什么特别的地方。但为什么要把它拿出来单独成一篇呢?这是因为它跟DSL有很大关系,是Groovy语言实现DSL的一种方式。
下面就来说一说如何使用“.”运算符来实现DSL的。
一直以来,我们都希望计算机能够识别我们人类的自然语言,如它能够帮我们计算这样的题目:
12元+39毛+123分
当然,现在的计算机还不能做到这样的场景。但是,现在有了DSL,我们能做到这样的场景:
12.yuan+39.jiao+123.fen
这样,就相当的接近我们的自然语言了。那么,Groovy语言是怎么实现上面的场景的呢?
一看到“12.yuan”这样的表达式,我们就可以想到,这不就是一个取值运算吗?我们可以重载“.”运算符。
不错,Groovy语言正是通过重载“.”运算符帮我们实现上面的场景的。既然要重载“.”运算符,那么“12”又是一个什么对象呢?在Groovy语言中一切都是对象,“12”是一个Integer对象。
对啦,我们只需要在Integer类里实现getYuan()方法,就可以重载取值运算符。但Integer类是一个已经存在的类,我们不能直接修改它。
那么我们怎么给Integer类添加getYuan()方法呢?是的,通过metaClass,即元对象。
下面是实现上面的场景的代码:
def mc = new ExpandoMetaClass(Integer.class,true)
mc.getYuan <<
{
->
delegate as float
}
mc.getJiao <<
{
->
def j = delegate as float
j/10
}
mc.getFen <<
{
->
def f = delegate as float
f/100
}
mc.initialize()
首先取得Integer类的元对象:“def mc = new ExpandoMetaClass(Integer.class,true)”。
然后,再添加各个“get”方法,因为我们只需要实现取值运算,因此,只需要实现“get”方法就可以了。
最后实例化这个元对象,即“mc.initialize()”
现在,我们来测试这段代码:
println 12.yuan+45.jiao+33.fen
结果为:
16.83
运算符的重载是Groovy语言实现DSL的一个很重要的方面,因此,我们拿出两个章节才把它说完,希望我们在今后的编码实践中经常的使用到它。