隐式传值\隐式转换
隐式值获取
分别使用implicit和implicitly关键字声明隐式值和隐式注入等操作
使用implicitly[类型],必须保证当前上下文有且仅有一个隐式值类型,一般这种隐式值变量的声明写在object单例类或者伴生对象中。
implicit var a:Int= 1
var b = implicitly[Int]
print(b.toString)
隐式注入值
要求隐式注入的值一般都会写成柯理化形式并且保证需要隐式注入的值写在最后。
implicit var msg:String="hello"
def hao(name:String,msg:String):Unit={
println(s"$name,$msg")
}
def nan(name:String)(implicit msg:String){
println(s"$name,$msg")
}
hao("zhanghn","miss you")
nan("zhanghn")
隐式参数转换
通过隐式参数转换将参数不满足的类型转为所需类型,Scala在编译代码的时候,先尝试正常编译,如果发现编译类型不匹配,会尝试加载当前上下文中是否存在该类型和目标类型的一是转换(必须唯一),如果存在则编译通过
def main(args: Array[String]): Unit = {
implicit def strToStudent(str: String): Student = {
new Student(str)
}
hello(new Student("zhanghn"))
}
def hello(stu: Student): Unit = {
println("hello," + stu.name)
}
隐式方法增强
该方式是通过隐式转换将类的方法进行增强处理,当对目标对象调用不存在的方式时候,Scala会尝试加载当前上下文中是否存在该类的隐式增强类(这种转换严格意义上应该必须唯一,否则编译器会提示错误警告,并不影响执行),如果存在则编译通过。
class Pig (var name :String){
def eat():Unit={
println(s"$name is eat")
}
}
package demo3
object MyImplicits {
implicit class PigImplicits(pig:Pig){
def fly():Unit={
println(pig.name+"\tflying")
}
}
}
object TestImplicitly {
def main(args: Array[String]): Unit = {
var pig = new Pig("佩奇")
import demo3.MyImplicits._
pig.eat()
pig.fly()
}
}
Scala泛型
<:上边界限定
trait Keeper[U<:Animal]{
def keep(a:U)
}
表示Keeper的实现类只能是Animal和Animal的子类
>:下边界限定
trait Keeper[U>:Dog]{
def keep(a:U)
}
表示Keeper的实现类只能是Dog或者Dog的父类
<%试图限定
视图限定将会在后续版本移除,主要意思是指必须保证上下文中有能够提供一个隐式转换T <% U能够将T隐式转为U类型,如下所示要求上下文中能够尝试将一个Int类型隐式转换为Student类型。保证真个上下文中可以将一个Int类型看成是Student类型。
implicit def str2Stu(v:Int):Student={
new Student(v,"zhangsan")
}
def getStu[Int <% Student](v:Int):String={
v.name
}
T:A上下文绑定
表示上下文中必须存在这种隐式值A[T]隐式值,否则程序编译出错;可以在上下文中还没有隐式值的时候确保方法能编译成功
implicit val u1=new User[String]()
def sayInfomation[T:User](msg:T):Unit={
var u=implicitly[User[T]]
u.sayHello(msg)
}
要求上下文中必须有一个隐式值User[T]类型:
implicit val u1=new User[String]()
def sayInfomation[T](msg:T):Unit={
var u=implicitly[User[T]] //无法获取上下文的隐式值
u.sayHello(msg)
}
class User[T] {
def sayHello(t:T): Unit ={
println(t)
}
}
+A协变
class Covariant[+T](t:T) {
}
val c1 = new Covariant[Dog](new Dog("小狗"))
val c2 = new Covariant[SmallDog](new SmallDog("小狗",true))
var c3:Covariant[SmallDog]= c1 //error
var c4:Covariant[Dog]= c2
-A逆变
class Covariant[+T](t:T) {
}
val c1 = new Covariant[Dog](new Dog("小狗"))
val c2 = new Covariant[SmallDog](new SmallDog("小狗",true))
var c3:Covariant[SmallDog]= c1
var c4:Covariant[Dog]= c2 //error
A不变
class Covariant[T](t:T) {
}
val c1 = new Covariant[Dog](new Dog("小狗"))
val c2 = new Covariant[SmallDog](new SmallDog("小狗",true))
var c3:Covariant[SmallDog]= c1//error
var c4:Covariant[Dog]= c2 //error
var c5:Covariant[Dog]= c1
var c6:Covariant[SmallDog]= c2