In scala implicit funziona come :
Converter
Iniettore valore parametro
Esistono 3 tipi di utilizzo di implicito
Conversione del tipo implicita : converte l'errore che produce l'assegnazione nel tipo previsto
val x: String = "1"
val y: Int = x
String non è il sottotipo di Int , quindi l'errore si verifica nella riga 2. Per risolvere l'errore, il compilatore cercherà un tale metodo nell'ambito che ha una parola chiave implicita e accetta una stringa come argomento e restituisce un Int .
così
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!
Conversione implicita del ricevitore : generalmente tramite il destinatario chiamiamo le proprietà dell'oggetto, ad es. metodi o variabili. Quindi, per chiamare qualsiasi proprietà da un destinatario, la proprietà deve essere il membro della classe / oggetto di quel destinatario.
class Mahadi{
val haveCar:String ="BMW"
}
class Johnny{
val haveTv:String = "Sony"
}
val mahadi = new Mahadi
mahadi.haveTv // Error happening
Qui mahadi.haveTv produrrà un errore. Perché scala compilatore cercherà prima la haveTv proprietà Mahadi ricevitore. Non troverà. In secondo luogo cercherà un metodo nell'ambito con una parola chiave implicita che prende l' oggetto Mahadi come argomento e restituisce l' oggetto Johnny . Ma non ha qui. Quindi creerà un errore . Ma quanto segue va bene.
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
Iniezione implicita di parametri : se chiamiamo un metodo e non passiamo il suo valore di parametro, causerà un errore. Il compilatore scala funziona in questo modo: per prima cosa proverà a passare il valore, ma non otterrà alcun valore diretto per il parametro.
def x(a:Int)= a
x // ERROR happening
In secondo luogo, se il parametro ha una qualsiasi parola chiave implicita cercherà qualsiasi val nel campo di applicazione , che hanno lo stesso tipo di valore. In caso contrario, si verificherà un errore.
def x(implicit a:Int)= a
x // error happening here
Per risolvere questo problema, il compilatore cercherà una val implicita con il tipo di Int perché il parametro a ha una parola chiave implicita .
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.
Un altro esempio:
def l(implicit b:Int)
def x(implicit a:Int)= l(a)
possiamo anche scriverlo come-
def x(implicit a:Int)= l
Poiché ho un parametro implicito e nell'ambito del corpo del metodo x , esiste una variabile locale implicita (i parametri sono variabili locali ) a che è il parametro di x , quindi nel corpo del metodo x il valore dell'argomento implicito della firma del metodo è presentato dalla variabile del metodo locale x implicita (parametro) a
implicitamente .
Così
def x(implicit a:Int)= l
sarà nel compilatore in questo modo
def x(implicit a:Int)= l(a)
Un altro esempio:
def c(implicit k:Int):String = k.toString
def x(a:Int => String):String =a
x{
x => c
}
causerà un errore, perché c in x {x => c} ha bisogno di passare esplicitamente valore nell'argomento o val implicita nell'ambito .
Quindi possiamo rendere esplicitamente implicito il parametro letterale della funzione quando chiamiamo il metodo x
x{
implicit x => c // the compiler will set the parameter of c like this c(x)
}
Questo è stato usato nel metodo di azione di 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 non si menziona esplicitamente il parametro di richiesta come implicito, è necessario che sia stato scritto-
def index = Action{
request =>
Ok(views.html.formpage()(request))
}