1  隐式转换

隐式转换函数是以implicit关键字声明的带有单个参数的函数。这种函数将会自动应用,将值从一种类型转换为另一种类型。

implicit def a(d: Double) = d.toInt
//不加上边这句你试试
val i1: Int = 3.5
println(i1)

2  利用隐式转换丰富类库功能

如果需要为一个类增加一个方法,可以通过隐式转换来实现。比如想为File增加一个read方法,可以如下定义:

class RichFile(val from: File) {
def read = Source.fromFile(from.getPath).mkString
}

implicit def file2RichFile(from: File) = new RichFile(from)

val contents = new File("C:\\Users\\61661\\Desktop\\scala笔记.txt").read
println(contents)

有什么好处呢?好处就是你可以不修改原版本的代码而为原本的代码增加新功能。

3  隐式值

将name变量标记为implicit,所以编译器会在方法省略隐式参数的情况下去搜索作用域内的隐式值作为缺少参数。

implicit val name = "Nick"
def person(implicit name: String) = name
println(person)

但是如果此时你又相同作用域中定义一个隐式变量,再次调用方法时就会报错:出现二义性

implicit val name = "Nick"
implicit val name2 = "Nick"
def person(implicit name: String) = name
println(person)

4  隐式视图

1)  隐式转换为目标类型:把一种类型自动转换到另一种类型

def foo(msg : String) = println(msg)
implicit def intToString(x : Int) = x.toString
foo(10)

2)  隐式转换调用类中本不存在的方法

class Dog {
val name = "金毛"
}

class Skill{
def fly(animal: Dog, skill: String) = println(animal.name + "已领悟" + skill)
}

object Learn{
implicit def learningType(s : Dog) = new Skill
}

object Main2 extends App{
override def main(args: Array[String]): Unit = {
import unit15.Learn._
val dog = new Dog
dog.fly(dog, "飞行技能")
}
}

当然了,以上操作也可以定义在包对象中,即,在object Learn的外面再套一层,package,没问题的!

5  隐式类

在scala2.10后提供了隐式类,可以使用implicit声明类,但是需要注意以下几点:

--  其所带的构造参数有且只能有一个

--  隐式类必须被定义在“类”或“伴生对象”或“包对象”里

--  隐式类不能是case class(case class在定义会自动生成伴生对象与2矛盾)

--  作用域内不能有与之相同名称的标示符

object StringUtils {
implicit class StringImprovement(val s : String){ //隐式类
def increment = s.map(x => (x +1).toChar)
}
}
object Main3 extends App{
import unit15.StringUtils._
println("mobin".increment)
}

6  隐式的转换时机

1)  当方法中的参数的类型与目标类型不一致时

2)  当对象调用所在类中不存在的方法或成员时,编译器会自动将对象进行隐式转换

7  隐式解析机制

即编译器是如何查找到缺失信息的,解析具有以下两种规则:

1)  首先会在当前代码作用域下查找隐式实体(隐式方法、隐式类、隐式对象)。

2)  如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找。类型的作用域是指与该类型相关联的全部伴生模块,一个隐式实体的类型T它的查找范围如下:

a)  如果T被定义为T with A with B with C,那么A,B,C都是T的部分,在T的隐式解析过程中,它们的伴生对象都会被搜索。

b)  如果T是参数化类型,那么类型参数和与类型参数相关联的部分都算作T的部分,比如List[String]的隐式搜索会搜索List的伴生对象和String的伴生对象。

c)  如果T是一个单例类型p.T,即T是属于某个p对象内,那么这个p对象也会被搜索。

d)  如果T是个类型注入S#T,那么S和T都会被搜索。

8  隐式转换的前提

1)  不能存在二义性

2)  隐式操作不能嵌套