Voici quelques raisons d'utiliser le délicieusement simple méthode implicitly
.
Pour comprendre/résoudre Implicite Vues
Implicite de Vue peut être déclenchée lorsque le préfixe de sélection (par exemple, the.prefix.selection(args)
ne contient pas un membre de l' selection
qui est applicable à la args
(même après avoir essayé de convertir args
avec les points de Vue). Dans ce cas, le compilateur recherche pour les membres implicites, définies localement dans le courant ou en joignant étendues, hérité, ou importés, qui sont Fonctions du type de l' the.prefix
à un type avec selection
défini, ou l'équivalent implicite des méthodes.
scala> 1.min(2) // Int doesn't have min defined, where did that come from?
res21: Int = 1
scala> implicitly[Int => { def min(i: Int): Any }]
res22: (Int) => AnyRef{def min(i: Int): Any} = <function1>
scala> res22(1) //
res23: AnyRef{def min(i: Int): Int} = 1
scala> .getClass
res24: java.lang.Class[_] = class scala.runtime.RichInt
Implicite points de Vue peut également être déclenchée lorsqu'une expression n'est pas conforme au Type Attendu, comme ci-dessous:
scala> 1: scala.runtime.RichInt
res25: scala.runtime.RichInt = 1
Ici, le compilateur recherche pour cette fonction:
scala> implicitly[Int => scala.runtime.RichInt]
res26: (Int) => scala.runtime.RichInt = <function1>
L'accès à un Paramètre Implicite Introduit par un Contexte Lié
Paramètres implicites sont sans doute un élément plus important de la Scala qu'Implicite points de Vue. Ils ont en charge le type de la classe de modèle. La bibliothèque standard utilise dans quelques endroits, voir scala.Ordering
et comment il est utilisé dans SeqLike#sorted
. Paramètres implicites sont également utilisés pour passer de la Matrice se manifeste, et CanBuildFrom
des cas.
Scala 2.8 permet une abréviation de la syntaxe pour les paramètres implicites, appelé Contexte de Limites. Brièvement, une méthode avec un paramètre de type A
qui nécessite un paramètre implicite de type M[A]
:
def foo[A](implicit ma: M[A])
peut être réécrit comme suit:
def foo[A: M]
Mais quel est le point de passer le paramètre implicite, mais ne pas le nommer? Comment cela peut-il être utile lors de la mise en œuvre de la méthode de foo
?
Souvent, le paramètre implicite n'a pas besoin d'être renvoyé directement, il sera passé à travers implicite d'argument à une autre méthode qui est appelée. Si c'est nécessaire, vous pouvez toujours conserver le laconique signature de la méthode avec le Contexte Lié, et appelez - implicitly
pour matérialiser la valeur:
def foo[A: M] = {
val ma = implicitly[M[A]]
}
Le passage d'un sous-ensemble de paramètres implicites explicitement
Supposons que vous appelez une méthode assez imprime une personne, à l'aide d'un type de classe de l'approche fondée sur:
trait Show[T] { def show(t: T): String }
object Show {
implicit def IntShow: Show[Int] = new Show[Int] { def show(i: Int) = i.toString }
implicit def StringShow: Show[String] = new Show[String] { def show(s: String) = s }
def ShoutyStringShow: Show[String] = new Show[String] { def show(s: String) = s.toUpperCase }
}
case class Person(name: String, age: Int)
object Person {
implicit def PersonShow(implicit si: Show[Int], ss: Show[String]): Show[Person] = new Show[Person] {
def show(p: Person) = "Person(name=" + ss.show(p.name) + ", age=" + si.show(p.age) + ")"
}
}
val p = Person("bob", 25)
implicitly[Show[Person]].show(p)
Si nous voulons changer la façon dont le nom est sortie? Nous pouvons appeler explicitement PersonShow
, transmettre explicitement une alternative Show[String]
, mais nous voulons que le compilateur pour passer l' Show[Int]
.
Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)