作用:
把原本对象没有方法,通过隐式转换变为有
方法:
1.将方法或变量标记为implicit
2.将方法的参数列表标记为implicit
3.将类标记为implicit
使用方式:
1.隐式值:用于给方法提供参数
2.隐式视图:用于类型间转换或使针对某类型的方法能调用成功
例1:
def person(implicit name : String) = name //name为隐式参数 person: (implicit name: String)String
// 执行 直接会报错 因为没有传参
person()
// 但是加入一个隐式变量 再调用 就正常了
implicit val p = "mobin"
person()
// 不过再多定义一个隐式变量 就又不正常了 产生歧义 编译器不知道该找哪个了
implicit val p1 = "mobin1"
person() // error
例2:
def foo(msg : String) = println(msg)
foo(10) // 出错 因为参数要求字符串 传了一个INT进去
// 定义一个隐式转换视图(实际上就是调用int对象默认不存在的转换函数方法) 再去调用 就正常了
implicit def intToString(x : Int) = x.toString
foo(10)
例3:
class SwingType{
def wantLearned(sw : String) = println("兔子已经学会了"+sw)
}
object swimming{
implicit def learningType(s : AminalType) = new SwingType
}
class AminalType
object AminalType extends App{
// 导入类的所有方法
import com.mobin.scala.Scalaimplicit.swimming._
val rabbit = new AminalType
// 本来rabbit不存在wantLearned方法 但是隐式导入了def learningType(s : AminalType)方法, 具备了这个方法
rabbit.wantLearned("breaststroke")
}
例4:
class SwingType{
def wantLearned(sw : String) = println("兔子已经学会了"+sw)
}
package swimmingPage{
object swimming{
implicit def learningType(s : AminalType) = new SwingType //将转换函数定义在包中
}
}
class AminalType
object AminalType extends App{
//和例三的区别是 这里是导入包里的
import com.mobin.scala.Scalaimplicit.swimmingPage.swimming._
val rabbit = new AminalType
rabbit.wantLearned("breaststroke") //蛙泳
}
原型为:
implicit def originalToTarget (<argument> : OriginalType) : TargetType
隐式类:
scala2.10以后提供
要求:
1.其所带的构造参数有且只能有一个
2.隐式类必须被定义在类,伴生对象和包对象里
3.隐式类不能是case class(case class在定义会自动生成伴生对象与2矛盾)
4.作用域内不能有与之相同名称的标示符
例5:
object Stringutils {
implicit class StringImprovement(val s : String){ //隐式类
def increment = s.map(x => (x +1).toChar)
}
}
object Main extends App{
import com.mobin.scala.implicitPackage.Stringutils._
println("mobin".increment)
}
隐式转换的时机:
1.当方法中的参数的类型与目标类型不一致时
2.当对象调用类中不存在的方法或成员时,编译器会自动将对象进行隐式转换
隐式解析机制 即编译器是如何查找到缺失信息的,解析具有以下两种规则:
1.首先会在当前代码作用域下查找隐式实体(隐式方法 隐式类 隐式对象)
2.如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找
类型的作用域是指与该类型相关联的全部伴生模块,一个隐式实体的类型T它的查找范围如下:
(1)如果T被定义为T with A with B with C,那么A,B,C都是T的部分,在T的隐式解析过程中,它们的伴生对象都会被搜索
(2)如果T是参数化类型,那么类型参数和与类型参数相关联的部分都算作T的部分,比如List[String]的隐式搜索会搜索List的
伴生对象和String的伴生对象
(3) 如果T是一个单例类型p.T,即T是属于某个p对象内,那么这个p对象也会被搜索
(4) 如果T是个类型注入S#T,那么S和T都会被搜索
隐式转换的前提:
1.不存在二义性(如例1)
2.隐式操作不能嵌套使用(如 convert1(covert2(x)))+y
3.代码能够在不使用隐式转换的前提下能编译通过,就不会进行隐式黑铁