在scala中,隐式工作方式为:
转换器
参数值注入器
扩展方法
这里有一些隐式的用法
隐式类型转换:将产生错误的赋值转换为预期的类型
val x:字符串= "1"
val y:Int = x
String不是Int的子类型,所以错误发生在第2行。为了解决这个错误,编译器将在范围内寻找这样一个方法,该方法具有隐式关键字,并以String作为参数并返回Int。
so
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!
隐式接收器转换:我们通常通过接收器调用对象的属性,如。方法或变量。因此,接收器要调用任何属性,该属性必须是接收器的类/对象的成员。
类Mahadi {
val haveCar:字符串="宝马"
}
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 //错误发生
其次,如果形参有任何隐式关键字,它将在作用域中查找具有相同类型值的任何val。如果得不到就会造成错误。
def x(implicit a:Int)= a
x // error happening here
为了解决这个问题,编译器将寻找具有Int类型的隐式值,因为形参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隐式填写。
So
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
为此,我们需要在对象/类/trait中创建一个隐式类。这个类不能是案例类。
object Extensions{
implicit class MeterToCm(meter:Int){
def meterToCm={
meter*100
}
}
}
注意,隐式类只接受一个构造函数形参。
现在在您想要使用的范围中导入隐式类
import Extensions._
2.meterToCm // result 200