In [1]:
def foo(msg: String) = println(msg)
In [2]:
foo(5)
由于类型不匹配,出现编译失败的错误提示。我们需要进行隐式转换来完成调用。
In [3]:
implicit def intToString(x: Int) = x.toString
In [4]:
foo(5)
In [5]:
Map("one" -> 1, "two" -> 2)
上面的方法调用了Map.apply方法,而该方法的输入时一组可变数量的pair对象:
def apply[A, B](elems: (A, B)*): Map[A, B]
这里并没有见到->方法的使用,所以其实->方法使用了隐式转换。
通过隐式转换,将任意两种类型值之间插入函数->,将表达式a -> b转换为元组(a, b)。
如果我们为所有可能作为元组首元素的类型都添加->方法肯定不现实。定义该方法的技巧是使用一个具有->方法的“封装”对象,Scala在Predef对象中定义了该对象:
implicit final class ArrowAssoc[A](private val self: A) extends AnyVal {
@inline def -> [B](y: B): Tuple2[A, B] = Tuple2(self, y)
def →[B](y: B): Tuple2[A, B] = ->(y)
}
我们可以依照上面的定义来构造Map对象:
In [6]:
Map(new ArrowAssoc("one") -> 1, new ArrowAssoc("two") -> 2)
由于ArrowAssoc类被声明为implicit类,因此编译器将执行下列逻辑:
编译器进行查找和使用隐式转换方法时的查询规则:
下面,我们通过隐式转换为StringContext添加新的方法,对其进行扩展,定义新的插入器。编写一个将简单JSON字符串转换为scala.util.parsing.JSONObject对象的插入器(该插入器功能简单,只处理扁平的JSON表达式)。
In [7]:
// Scala 2.11中,json包被放置在一个独立的解析器-组合器库中,这里需要加载jar包
load.jar("D:\\scala\\lib\\scala-parser-combinators_2.11-1.0.4.jar")
In [8]:
import scala.util.parsing.json._
object Interpolators {
implicit class jsonForStringContext(val sc: StringContext) { //为了限制隐式类的作用域,必须在对象内定义隐式类
def json(values: Any*): JSONObject = { //该方法输入字符串中嵌套的参数,返回JSONObject对象
val keyRE = """^[\s{,]*(\S+):\s*""".r //抽取key名称的正则表达式
val keys = sc.parts map {
case keyRE(key) => key
case str => str
}
val kvs = keys zip values // 将key和value压缩成键值对集合
JSONObject(kvs.toMap) //使用键值对构成Map对象,并构造JSONObject对象
}
}
}
In [9]:
import Interpolators._
val name = "Dean Wampler"
val book = "Programming Scala, Second Edition"
val jsonobj = json"{name: $name, book: $book}"
println(jsonobj)