Suche…


Einführung

Mit Scala können Sie dynamisches Aufrufen verwenden, wenn Sie Methoden aufrufen oder auf Felder eines Objekts zugreifen. Anstatt diese tief in die Sprache zu integrieren, wird dies durch Umschreiben von Regeln erreicht, die denen impliziter Konvertierungen ähnlich sind, die durch das Merkmalsmerkmal [ scala.Dynamic ] [Dynamic scaladoc] ermöglicht werden. Auf diese Weise können Sie die Fähigkeit zum dynamischen Hinzufügen von Eigenschaften zu Objekten in dynamischen Sprachen usw. emulieren. [Dynamic scaladoc]: http://www.scala-lang.org/api/2.12.x/scala/Dynamic.html

Syntax

  • Klasse Foo erweitert Dynamic
  • foo.field
  • foo.field = Wert
  • foo.method (args)
  • foo.method (namedArg = x, y)

Bemerkungen

Um Subtypen zu erklären Dynamic , die Sprache - Funktion dynamics muss aktiviert werden, entweder durch den Import scala.language.dynamics oder durch die -language:dynamics - Compiler - Option. Benutzer dieses Dynamic , die keine eigenen Subtypen definieren, müssen dies nicht aktivieren.

Feldzugriffe

Diese:

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) = ???
}

ermöglicht den einfachen Zugriff auf Felder:

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.

Methodenaufrufe

Diese:

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)
  }
}

erlaubt Aufrufe von Methoden mit und ohne benannte Parameter:

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)

Interaktion zwischen Feldzugriff und Aktualisierungsmethode

Etwas uninteressant (aber auch der einzige vernünftige Weg, damit es funktioniert):

val dyn: Dynamic = ???
dyn.x(y) = z

ist äquivalent zu:

dyn.selectDynamic("x").update(y, z)

während

dyn.x(y)

ist immer noch

dyn.applyDynamic("x")(y)

Es ist wichtig, sich dessen bewusst zu sein, andernfalls könnte es unbemerkt schleichen und seltsame Fehler verursachen.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow