隐式转换
定义:
以implicit关键字声明的带有单个参数的函数。
implicit def int2Fraction(n: Int) = Fraction(n, 1)
val result = 3 * Fraction(4, 5) //调用int2Fraction(3)
//隐式转换将整数3转换成了一个Fraction对象。这个对象又被乘以Fraction(4, 5)
利用隐式转换丰富现有类库的功能
class RichFile(val from: File) {
def read = Source.fromFile(from.getPath).mkString
}
implicit def file2RichFile(from: File) = new RichFile(name)
//这样你就可以在File对象上调用read方法了。
引用隐式转换
Scala会考虑如下的隐式转换函数:
1. 位于源或目标类型的伴生对象中的隐式函数。
2. 位于当前作用域可以以单个标识符指代的隐式函数。
import com.lianle.impatient.FractionConversions._
隐式转换规范
三种情况会考虑:
1. 当表达式的类型与预期的类型不同时;
2. 当对象访问一个不存在的成员时;
3. 当对象调用某个方法,而该方法的参数声明与传入参数不匹配时。
三种情况编译器不会考虑:
1. 如果代码能够在不使用隐式转换的前提下通过编译;
2. 编译器不会尝试同时执行多个转换;
3. 存在二义性的转换是个错误。
隐式参数
case class Delimiters(left: String, right: String)
def quote(what: String)(implicit delime: Delimiters) =
delims.left + what + delims.right
调用:
quote("Bonjour le monds")(Delimiters("<<",">>"))
//将返回<<Bonjour le monds>>
也可以略去隐式参数列表,得到相同效果:
quote("Bonjour le monds")
利用隐式参数进行隐式转换
def smaller[T] (a: T, b: T)(implicit order: T => Ordered[T]) = if (order(a) < b) a else b
上下文界定
类型参数可以有一个形式为T:M的上下文界定。其中M是另一个泛型类型,它要求作用域中存在一个类型为M[T]的隐式值。
class Pair[T: Ordering]
@implicitNotFount注解
@implicitNotFount注解告诉编译器在不能够在出带有该注解的类型的参数时给出错误提示。
@implicitNotFount(msg = "Cannot prove that ${From} <:<${To}.")
abstract class <:<[-From, + To] extends Funcion1[From, To]
例如:
firstLast[String, Lig[Int]](List(1, 2, 3))
//将提示:
//Cannot prove that List[Int] <:<Iterable[String].
CanBuildFrom解读
CanBuidFrom[From, E, To]特质将提供类型证明,可以创建一个类型为To的集合,握有类型为E的值,并且和类型From兼容。
CanBuidFrom特质带有一个apply方法,产生类型为Builder[E, To]的对象。
Builder类型带有一个+= 方法用来将元素添加到一个内部的缓冲,还有一个result方法用来产出所要求的集合。
trait Builder[-E, +To] {
def +=(e: E) : Unit
def result(): To
}
trait CanBuidFrom[-From, -E, +To] {
def apply(): Builder[E, To]
}