Groovy探索之运算符的重载 二

来源:互联网 发布:平邑网络招聘网站 编辑:程序博客网 时间:2024/05/23 21:14
 

          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的一个很重要的方面,因此,我们拿出两个章节才把它说完,希望我们在今后的编码实践中经常的使用到它。