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