Scala 中的 DSL


最近看了下 Scala程序设计,觉得里面的隐式类型转换蛮有趣的,可以写出DSL的效果。这篇小文就是想分享下如何写出类似" 2 days ago"和“2 days from_now"这样的代码。为了好玩点,我也会写一个" I Love You"这样的DSL,并且然后程序可以正常编译。首先看看如何写成”2 days ago" 这样的效果。请看如下代码:

package helper { import java.util.Calendar import java.util.Date class DateHelper private(number: Int) { def days(when: String): Date = { var date = Calendar.getInstance() when match { case DateHelper.ago => date.add(Calendar.DAY_OF_MONTH, -number) case DateHelper.from_now => date.add(Calendar.DAY_OF_MONTH, number) case _ => date } date.getTime() } } object DateHelper { val ago = "ago" val from_now = "from_now" implicit def convertInt2Date(number: Int) = new DateHelper(number) } }

 

简单分析下上面的代码。

首先,我们定义了一个名为helper的package,然后package里面定义一个private类型的DateHelper类以及其伴生对象。在伴生对象中,我们注意到有一个convertInt2Date方法,并且用"implicit"做了修饰。用"implicit"修改的方法很特殊,它会在类被导入时自动执行,并且将其参数进行隐式转换,如代码中将Int类型转换为了DateHelper类型。 这样当我们调用Int类型的方法时 会自动变为DateHelper类型。看看如何使用这个DateHelper就明白了。

import helper.DateHelper._ object Sample { def main(args: Array[String]): Unit = { val twoDayAgo = 2 days ago val twoDayAfter = 2 days from_now println("two days ago is " + twoDayAgo) println("two days after is " + twoDayAfter) } }

返回结果:

two days ago is Fri May 31 22:16:58 CST 2013 two days after is Tue Jun 04 22:16:58 CST 2013

事实上,"2 days ago" 相当于调用 2.days(ago), 因为Scala的方法中的点号可以省略,括号也可以省略,所以看起来就像DSL了。

也许有朋友会问,那这个"ago"怎么来的?好问题!我们看DateHelper的伴生对象,里面不是有定义了一个ago变量么,变量的值就是"ago", 然后导入DateHelper._时,将其也导入进来了,所以可以直接访问。其实就是 2.days("ago"), 换汤不换药而已。

调用DateHelper中的days方法时,我们用到了模式匹配,只有当传入的参数值为DateHelper.agoDateHelper.from_now时,我们才进行处理,其他情况一律返回当前日期。

很简单吧,但是真的很强大!现在,我们在看一个" I Love You"的效果。当代码中写入"I Love You" 时,程序打印出"I love You"

package love { class LoveHelper private(who: String) { def love(beLoved: String) = { beLoved match { case LoveHelper.You => println(who + " Love " + beLoved) case _ => println("You don't love " + beLoved ) } } } object LoveHelper { val I = "I" val You = "You" implicit def conver(who: String) = new LoveHelper(who) } }

程序调用:

import love.LoveHelper._ object LoveSample { def main(args: Array[String]): Unit = {  I love You I love "marry" } }

运行结果为:

I Love You You don't love marry

如果明白了DateHelper的例子,这个就非常简单了。这个代码是地String类型做了隐式转换,转换为LoveHelper对象,然后调用里面的love方法。

Scala真的非常强大,可以写成简单易读的DSL代码出来,为我们的coding life增加了不少色彩,大家也可以玩一玩哦!

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM