褪去Scala的糖衣(12) -- implicit function(补)
上次博客谈到了implicit function,但是漏掉了一些东西,今天补上。
由于上次已经讲过implicit function的实现细节,这次就不再重复了。今天只补充上次漏掉了的implicit function的一种很好的实践。
先看一段specs2的测试代码:
1 | import org.specs2.mutable._ |
我们试着理解这个测试代码在做什么的时候,无须多少思考,因为它和人类语言一样的亲近和自然。但是如果我们想知道specs2如何做到这一点时,就有点费解了。
我们知道xObject yMethod zParameter的写法是一个语法糖,它和xObject.yMethod(zParameter)是一样的。也就是说should和in都是方法名。于是,问题来了,should和in前面是个String啊,String上哪有这两个方法的定义?
想必答案你已经猜到了,specs2定义了一些implicit functions来把String转换成能够调用should和in的对象。至于是哪些对象,因为涉及到了specs2的细节,我们暂不讨论。我们试着模仿specs2来写出一段类似人类语言的代码:
1 | class Person(name: String) { |
定义一个Person类,Person有一个名字,只会做一件事:吃。
然后我们可以这样调用它:
1 | new Person("Xiao ming").eat("steamed dumplings") |
我们让小明吃点蒸饺。或者也可以这样:
1 | new Person("Xiao ming") eat "boiled dumplings" |
再煮点饺子让小明吃。这就是我们前面提到过的xObject yMethod zParameter的写法了。让小明吃点东西还得new一个Person出来,这太麻烦了,我们定义一个implicit function:
1 | implicit def stringToPerson(name: String) = new Person(name) |
这样就可以把String转换成Person了。然后就可以像这样写:
1 | "Xiao ming" eat "more dumplings" |
虽然我们写的是“Xiao ming”,但是编译器会把stringToPerson的调用加上去,然后才调用eat方法。
这行代码看起来已经很接近人类语言了。
连吃三顿饺子,明哥,您饱了吧?