Zoeken…


Invoering

Met Scala kunt u dynamische aanroep gebruiken bij het aanroepen van methoden of het openen van velden op een object. In plaats van dit diep in de taal te hebben ingebouwd, wordt dit bereikt door regels te herschrijven die vergelijkbaar zijn met die van impliciete conversies, mogelijk gemaakt door het kenmerk [ scala.Dynamic ] [Dynamic scaladoc]. Hiermee kunt u de mogelijkheid emuleren om dynamisch eigenschappen toe te voegen aan objecten in dynamische talen, en meer. [Dynamische scaladoc]: http://www.scala-lang.org/api/2.12.x/scala/Dynamic.html

Syntaxis

  • klasse Foo breidt Dynamic uit
  • foo.field
  • foo.field = waarde
  • foo.method (args)
  • foo.method (genaamdArg = x, y)

Opmerkingen

Om de subtypen Dynamic te declareren, moet de taalfunctie- dynamics zijn ingeschakeld, door scala.language.dynamics importeren of door de optie scala.language.dynamics -language:dynamics compiler. Gebruikers van deze Dynamic die geen eigen subtypen definiëren, hoeven dit niet in te schakelen.

Veldtoegang

Deze:

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

zorgt voor eenvoudige toegang tot velden:

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.

Methodeaanroepen

Deze:

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

maakt aanroepen van methoden mogelijk, met en zonder benoemde parameters:

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)

Interactie tussen veldtoegang en updatemethode

Iets contra-intuïtief (maar ook de enige verstandige manier om het te laten werken), dit:

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

is gelijk aan:

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

terwijl

dyn.x(y)

is nog steeds

dyn.applyDynamic("x")(y)

Het is belangrijk om u hiervan bewust te zijn, anders kan het onopgemerkt sluipen en vreemde fouten veroorzaken.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow