수색…


소개

Scala를 사용하면 메서드를 호출하거나 객체의 필드에 액세스 할 때 동적 호출을 사용할 수 있습니다. 이것을 언어에 깊이 scala.Dynamic 시키는 대신 마커 특성 [ scala.Dynamic ] [Dynamic scaladoc]을 사용하여 암시 적 변환과 유사한 규칙을 다시 작성하여 수행합니다. 이를 통해 동적 언어로 표시되는 객체 등에 속성을 동적으로 추가하는 기능을 에뮬레이션 할 수 있습니다. [동적 scaladoc] : http://www.scala-lang.org/api/2.12.x/scala/Dynamic.html

통사론

  • Foo 클래스는 Dynamic을 확장합니다.
  • foo.field
  • foo.field = value
  • foo.method (args)
  • foo.method (이름이 지정된 Arg = x, y)

비고

Dynamic 하위 유형을 선언하려면 scala.language.dynamics 를 가져 오거나 -language:dynamics 컴파일러 옵션을 사용하여 언어 기능 dynamics 을 활성화해야합니다. 자신의 부속 유형을 정의하지 않는이 Dynamic 사용자는 이것을 사용할 필요가 없습니다.

필드 액세스

이:

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

필드에 대한 간단한 액세스를 허용합니다.

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.

메소드 호출

이:

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

명명 된 매개 변수의 유무에 관계없이 메서드 호출을 허용합니다.

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)

필드 액세스와 업데이트 방법 간의 상호 작용

약간 반 직관적으로 (그러나 작동시키기위한 유일한 제정 방법) 이것은 다음과 같습니다.

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

다음과 같습니다.

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

동안

dyn.x(y)

아직

dyn.applyDynamic("x")(y)

이 사실을 알고 있어야합니다. 그렇지 않으면 눈에 띄지 않게 몰래 들어가 이상한 오류가 발생할 수 있습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow