Em scala, o implícito funciona como :
Conversor
Injetor de valor de parâmetro
Existem 3 tipos de uso do Implicit
Conversão implícita de tipos : converte o erro na produção da atribuição no tipo pretendido
val x: String = "1"
val y: Int = x
String não é o subtipo de Int , portanto, o erro ocorre na linha 2. Para resolver o erro, o compilador procurará um método no escopo que tenha uma palavra-chave implícita e use uma String como argumento e retorne um Int .
tão
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!
Conversão implícita no receptor : Geralmente, pelo receptor chamamos as propriedades do objeto, por exemplo. métodos ou variáveis. Portanto, para chamar qualquer propriedade por um receptor, a propriedade deve ser o membro da classe / objeto desse receptor.
class Mahadi{
val haveCar:String ="BMW"
}
class Johnny{
val haveTv:String = "Sony"
}
val mahadi = new Mahadi
mahadi.haveTv // Error happening
Aqui mahadi.haveTv produzirá um erro. Porque compilador scala procurará primeiro para o haveTv propriedade para Mahadi receptor. Não vai encontrar. Segundo, procurará um método no escopo que possua uma palavra-chave implícita que tome o objeto Mahadi como argumento e retorne o objeto Johnny . Mas não tem aqui. Então, isso criará erro . Mas o seguinte está bem.
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
Injeção implícita de parâmetros : se chamarmos um método e não passarmos seu valor, isso causará um erro. O compilador scala funciona assim - primeiro tentará passar valor, mas não obterá valor direto para o parâmetro.
def x(a:Int)= a
x // ERROR happening
Em segundo lugar, se o parâmetro tem qualquer palavra-chave implícita ele vai olhar para qualquer val no âmbito que têm o mesmo tipo de valor. Caso contrário, causará erro.
def x(implicit a:Int)= a
x // error happening here
Para reduzir esse problema, o compilador procurará um valor implícito com o tipo de Int, porque o parâmetro a possui uma palavra-chave implícita .
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.
Outro exemplo:
def l(implicit b:Int)
def x(implicit a:Int)= l(a)
também podemos escrever como-
def x(implicit a:Int)= l
Porque eu possui um parâmetro implícito e no escopo do corpo do método x , existe uma variável local implícita ( parâmetros são variáveis locais ) a que é o parâmetro de x , portanto, no corpo do método x , o valor implícito do argumento da assinatura do método l é arquivado pela variável implícita local do método x (parâmetro) a
implicitamente .
assim
def x(implicit a:Int)= l
estará no compilador como este
def x(implicit a:Int)= l(a)
Outro exemplo:
def c(implicit k:Int):String = k.toString
def x(a:Int => String):String =a
x{
x => c
}
causará erro, porque c em x {x => c} precisa passar explicitamente o valor ou argumento implícito no escopo .
Assim, podemos fazer a função do literal parâmetro explicitamente implícita quando chamamos os métodos x
x{
implicit x => c // the compiler will set the parameter of c like this c(x)
}
Isso foi usado no método de ação do 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())
}
se você não mencionar o parâmetro request como implícito explicitamente, deverá ter sido escrito-
def index = Action{
request =>
Ok(views.html.formpage()(request))
}