在 scala 中隐式工作为:
转换器
参数值注入器
扩展方法
隐式有一些用途
-
隐式类型转换:它将产生错误的赋值转换为预期类型
val x :String = "1"
val y:Int = x
String 不是 Int 的 子类型,因此在第 2 行会发生错误。为了解决错误,编译器将在具有隐式关键字并将 String 作为参数并返回 Int 。
所以
implicit def z(a:String):Int = 2
val x :String = "1"
val y:Int = x // compiler will use z here like val y:Int=z(x)
println(y) // result 2 & no error!
-
隐式接收器转换:我们一般通过接收器调用对象的属性,例如。方法或变量。因此,要由接收者调用任何属性,该属性必须是该接收者的类/对象的成员。
class Mahadi{
val haveCar:String ="BMW"
}
class Johnny{
val haveTv:String = "Sony"
}
val mahadi = new Mahadi
mahadi.haveTv // Error happening
这里 mahadi.haveTv 会产生错误。因为 scala 编译器会首先寻找 haveTv 属性给 mahadi 接收器。它不会找到。其次,它将在具有 隐式关键字 的范围内寻找一个方法,该方法以 Mahadi 对象 作为参数并返回 Johnny 对象。但是这里没有。所以它会产生错误。但是下面的没问题。
class Mahadi{
val haveCar:String ="BMW"
}
class Johnny{
val haveTv:String = "Sony"
}
val mahadi = new Mahadi
implicit def z(a:Mahadi):Johnny = new Johnny
mahadi.haveTv // compiler will use z here like new Johnny().haveTv
println(mahadi.haveTv)// result Sony & no error
-
隐式参数注入:如果我们调用一个方法并且不传递它的参数值,就会导致错误。 scala 编译器的工作方式是这样的——首先会尝试传递值,但它不会得到参数的直接值。
def x(a:Int)= a
x // ERROR happening
其次,如果参数有任何隐式关键字,它将在 范围 中查找具有 相同类型 值的任何 val。如果没有得到它会导致错误。
def x(implicit a:Int)= a
x // error happening here
为了解决这个问题,编译器会寻找一个 int 类型的 implicit val,因为参数 a 有 implicit 关键字。
def x(implicit a:Int)=a
implicit val z:Int =10
x // compiler will use implicit like this x(z)
println(x) // will result 10 & no error.
另一个例子:
def l(implicit b:Int)
def x(implicit a:Int)= l(a)
我们也可以这样写-
def x(implicit a:Int)= l
因为l有一个隐式参数并且在方法x的主体范围内,有一个隐式局部变量(参数是局部变量) a是x的参数,所以在x的主体 方法方法签名l的隐含参数值由x方法的局部隐含变量(参数)a隐含归档。
所以
def x(implicit a:Int)= l
将像这样在编译器中
def x(implicit a:Int)= l(a)
另一个例子:
def c(implicit k:Int):String = k.toString
def x(a:Int => String):String =a
x{
x => c
}
这会导致错误,因为 x{x=>c} 中的 c 需要在参数中显式传递值或在范围内隐式传递值强>。
所以当我们调用方法x
时,我们可以使函数字面量的
parameter显式
implicit
x{
implicit x => c // the compiler will set the parameter of c like this c(x)
}
这已经用于Play-Framework的action method
in view folder of app the template is declared like
@()(implicit requestHreader:RequestHeader)
in controller action is like
def index = Action{
implicit request =>
Ok(views.html.formpage())
}
如果你没有明确提到请求参数是隐式的,那么你一定是被写了-
def index = Action{
request =>
Ok(views.html.formpage()(request))
}
- 扩展方法
想一想,我们想用 Integer 对象添加新方法。该方法的名称将是meterToCm,
> 1 .meterToCm
res0 100
为此,我们需要在 object/class/trait 中创建一个隐式类。这个类不能是case类。
object Extensions{
implicit class MeterToCm(meter:Int){
def meterToCm={
meter*100
}
}
}
注意隐式类只会采用一个构造函数参数。
现在在你想要使用的范围内导入隐式类
import Extensions._
2.meterToCm // result 200