在 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 编译器会首先寻找mahadi接收器的haveTv属性。它不会找到。其次,它将在范围内寻找一个具有隐式关键字的方法,该方法以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 类型的隐式 val ,因为参数a具有隐式关键字。
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需要在参数中显式传递值或在范围内隐式传递 val 。
因此,当我们调用方法 x时,我们可以使函数字面量的参数显式隐式
x{
implicit x => c // the compiler will set the parameter of c like this c(x)
}
这已用于Play-Framework的动作方法
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 中创建一个隐式类。该类不能是案例类。
object Extensions{
implicit class MeterToCm(meter:Int){
def meterToCm={
meter*100
}
}
}
请注意,隐式类将只采用一个构造函数参数。
现在在您要使用的范围内导入隐式类
import Extensions._
2.meterToCm // result 200