隐式转换

首页scala隐式转换(2018年11月29日)

作用:

把原本对象没有方法,通过隐式转换变为有

方法:
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.代码能够在不使用隐式转换的前提下能编译通过,就不会进行隐式黑铁

标签: none

评论已关闭