参考
《 scala in depth》by Joshua D.Suereth
场景
scala隐式转换系统中转换规则彻底解说
分析
scala以语法简洁与功能强大著称,而语法简洁在很大程度上得意于scala的隐式转换系统。隐式转换系统能够使程序员少写一些代码 -天才编译器在编译时能自动推导出你所简写的那些代码,只要你是按照隐式转换规则来简写的(你可能在想,scala的编译器肿么这么真强悍啊,要知道scala的作者Martin正是java编译器的作者,哈哈,外星人)
- 隐式参数
一、隐式元素(类、方法、变量、常量等被implicit关键在修饰的元素)查找规则:
1、隐式元素在查找域内可见(就是说编译器能推断出该隐式元素)
2、如果按第一条没有找到,则会在隐式参数T的隐式作用域里所包含的所有隐式元素里查找。
隐式参数T的隐式作用域:与T类型关联的所有类型的伴生对象集合。其中与T类型关联的元素包括:
1)T的全部父类。
2)T是类型化参数,比如 T[A] 那么 A 的伴生对象也会被搜索。
3)如果T位于某个对象内,那么这个对象也会被搜索(p.T => p的伴生对象也会被搜索)。
4)如果T位于某个类或者特质内,那么这个类或者特质也会被搜索。
注:隐式元素前面不能有前缀修饰,否则无法被搜索到。eg、foo.x,就无法查找到,而 x 可以。
二、实验
package cool.pengych.scala.myimplicit
import cool.pengych.scala.myimplicit.Person.Women
/**
* Created by pengyucheng on 16-4-12.
*/
trait Lover
object Lover{
implicit val lover = new Lover {
override def toString = "companion lover !"
}
}
trait Food
object Food{
implicit val list = List(new Food {})
}
object Person{
trait Women
implicit def getGirlFriend= new Women {
override def toString = "yeah, that's my baby !"
}
}
object ImplicityTest {
def main(args: Array[String]) {
/**
* 通过伴生对象获取隐式作用域,从而找到所需要的隐式元素(通过Lover的伴生对象Lover获取testCompanionSearch方法所需要的参数 lover)
*/
println(testCompanionSearch)
/**
* 通过类型参数获得隐式作用域(通过参数Food,在其伴生对象中找到 List[Food])
*/
println(testImplicitly[List[Food]])
println(implicitly[List[Food]])
/**
* 通过外部类或者对象获取隐式作用域(通过Women的外部对象Person获取其作用域,从而获得参数Women)
* 注意体会 统一访问原则:这里我只需要一个参数 Women,才不管这个Women 是通过方法返回还是,直接通过常量定义的)
*/
println(testOuterSearch)
println(implicitly[Person.Women])
}
def testCompanionSearch(implicit lover:Lover)=lover
def testImplicitly[T](implicit arg:T) = arg
def testOuterSearch(implicit girlFriend:Women)=girlFriend
}
执行结果
companion lover !
List(cool.pengych.scala.myimplicit.Food$$anon$2@5fc7f7)
List(cool.pengych.scala.myimplicit.Food$$anon$2@5fc7f7)
yeah, that's my baby !
- 隐式类与对象(待续)
总结