0
注意:lazy 不能修饰 var 类型的变量
隐式转换
隐式函数
隐式转换可以在不需改任何代码的情况下,扩展某个类的功能
练习:通过隐式转化为 Int 类型增加方法。
//创建一个隐式方法,在def 前面加上关键字 implicit 让一个类型具有更加丰富的功能
implicit def stringWrapper(str:String)={
new MyRichString(str)
}
class MyRichString(val str:String){
def fly()={
println(str+",我是字符串,我能飞!!")
}
def jump()={
str + ":我能跳!"
}
}
package com.doit.day02
import com.doit.day01.AnythingElse.Else._
/**
* 隐式转换:说白了就是给一个函数,参数,类 赋予更加强大的功能
*/
object _10_隐式转换 {
def main(args: Array[String]): Unit = {
//1 本身是int 类型的,但是他却可以调用richInt这个类里面的方法
/**
* implicit def intWrapper(x: Int)= {
* //相当于创建了一个 RichInt的对象
* new runtime.RichInt(x)
* }
* 我写了一个隐式方法,传进去一个参数,返回给我的是一个对象, 并且在这个方法最前面加上了implicit 关键字 ,那么
* 这个参数的类型 就具备了该类的方法
*/
val str: String = "zss"
str.fly()
}
}
隐式参数
普通方法或者函数中的参数可以通过 implicit 关键字声明为隐式参数,调用该方法时,
就可以传入该参数,编译器会在相应的作用域寻找符合条件的隐式值
说明:
- 同一个作用域中,相同类型的隐式值只能有一个
- 编译器按照隐式参数的类型去寻找对应类型的隐式值,与隐式值的名称无关。
- 隐式参数优先于默认参数
代码示例:
//定义了一个方法,方法中的参数设置的是隐式参数
def add(implicit a: Int, b: String) = {
a + b.toInt
}
//定义两个变量,前面用implicit 修饰 变成隐式的
implicit val a:Int = 10
implicit val b:String = "20"
//调用方法的时候,如果没有传参数,那么他会去上下文中找是否又隐式参数,如果有
//他就自己偷偷的传进去了,如果没有,会直接报错
add
隐式类
在 Scala2.10 后提供了隐式类,可以使用 implicit 声明类,隐式类的非常强大,同样可
以扩展类的功能,在集合中隐式类会发挥重要的作用。
说明:
- 其所带的构造参数有且只能有一个
- 隐式类必须被定义在“类”或“伴生对象”或“包对象”里,即隐式类不能是顶级的。
代码示例:
implicit class snake(ant:Ant){
def eatElephant()={
println("i can eat elephant!!")
}
}
val ant: Ant = new Ant
ant.eatElephant()
隐式解析机制
- 首先会在当前代码作用域下查找隐式实体(隐式方法、隐式类、隐式对象)。
- 如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找。类型的作用域是指与该类型相关联的全部伴生对象以及该类型所在包的包对象。
代码示例:
package com.chapter10
import com.chapter10.Scala05_Transform4.Teacher
//(2)如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找。
类型的作用域是指与该类型相关联的全部伴生模块,
object TestTransform extends PersonTrait {
def main(args: Array[String]): Unit = {
//(1)首先会在当前代码作用域下查找隐式实体
val teacher = new Teacher()
teacher.eat()
teacher.say()
}
class Teacher {
def eat(): Unit = {
println("eat...")
}
}
}
trait PersonTrait {
}
object PersonTrait {
// 隐式类 : 类型 1 => 类型 2
implicit class Person5(user:Teacher) {
def say(): Unit = {
println("say...")
}
}
}