Scala Language
Invocation dynamique
Recherche…
Introduction
Scala vous permet d'utiliser l'appel dynamique lors de l'appel de méthodes ou de l'accès aux champs d'un objet. Au lieu de l'
scala.Dynamic
au langage, cela est possible grâce à la réécriture de règles similaires à celles des conversions implicites, activées par le trait de marqueur [ scala.Dynamic
] [Dynamic scaladoc]. Cela vous permet d'émuler la possibilité d'ajouter dynamiquement des propriétés aux objets présents dans les langages dynamiques, et plus encore. [Scaladoc dynamique]: http://www.scala-lang.org/api/2.12.x/scala/Dynamic.html
Syntaxe
- classe Foo étend Dynamic
- foo.field
- foo.field = valeur
- foo.method (args)
- foo.method (namedArg = x, y)
Remarques
Afin de déclarer les sous-types de Dynamic
, la dynamics
scala.language.dynamics
linguistiques doit être activée, soit en important scala.language.dynamics
soit en -language:dynamics
option de compilation -language:dynamics
. Les utilisateurs de cette Dynamic
qui ne définissent pas leurs propres sous-types n'ont pas besoin de l'activer.
Accès aux champs
Ce:
class Foo extends Dynamic {
// Expressions are only rewritten to use Dynamic if they are not already valid
// Therefore foo.realField will not use select/updateDynamic
var realField: Int = 5
// Called for expressions of the type foo.field
def selectDynamic(fieldName: String) = ???
def updateDynamic(fieldName: String)(value: Int) = ???
}
permet un accès simple aux champs:
val foo: Foo = ???
foo.realField // Does NOT use Dynamic; accesses the actual field
foo.realField = 10 // Actual field access here too
foo.unrealField // Becomes foo.selectDynamic(unrealField)
foo.field = 10 // Becomes foo.updateDynamic("field")(10)
foo.field = "10" // Does not compile; "10" is not an Int.
foo.x() // Does not compile; Foo does not define applyDynamic, which is used for methods.
foo.x.apply() // DOES compile, as Nothing is a subtype of () => Any
// Remember, the compiler is still doing static type checks, it just has one more way to
// "recover" and rewrite otherwise invalid code now.
Appels de méthode
Ce:
class Villain(val minions: Map[String, Minion]) extends Dynamic {
def applyDynamic(name: String)(jobs: Task*) = jobs.foreach(minions(name).do)
def applyDynamicNamed(name: String)(jobs: (String, Task)*) = jobs.foreach {
// If a parameter does not have a name, and is simply given, the name passed as ""
case ("", task) => minions(name).do(task)
case (subsys, task) => minions(name).subsystems(subsys).do(task)
}
}
permet d'appeler des méthodes, avec et sans paramètres nommés:
val gru: Villain = ???
gru.blu() // Becomes gru.applyDynamic("blu")()
// Becomes gru.applyDynamicNamed("stu")(("fooer", ???), ("boomer", ???), ("", ???),
// ("computer breaker", ???), ("fooer", ???))
// Note how the `???` without a name is given the name ""
// Note how both occurrences of `fooer` are passed to the method
gru.stu(fooer = ???, boomer = ???, ???, `computer breaker` = ???, fooer = ???)
gru.ERR("a") // Somehow, scalac thinks "a" is not a Task, though it clearly is (it isn't)
Interaction entre l'accès aux champs et la méthode de mise à jour
Légèrement contre-intuitif (mais aussi la seule façon saine de le faire fonctionner), ceci:
val dyn: Dynamic = ???
dyn.x(y) = z
est équivalent à:
dyn.selectDynamic("x").update(y, z)
tandis que
dyn.x(y)
est encore
dyn.applyDynamic("x")(y)
Il est important d'être conscient de cela, sinon il peut passer inaperçu et causer des erreurs étranges.
Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow