scala作为一个严格的静态类型,它是支持动态类型的,当前他是属于实验性的,这里在实际的生产环境中是否是个good idea我也不晓得
类似宏我们得在编译器中开启这个功能
import scala.language.dynamics
使用也是比较简单的,我们可以用idea直接查看Dynamic的源码,而且里面也包含了四个方法的使用,我们只要实现对应的方法就可以达到动态语言的效果了
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2010-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
package scala
/** A marker trait that enables dynamic invocations. Instances `x` of this
* trait allow method invocations `x.meth(args)` for arbitrary method
* names `meth` and argument lists `args` as well as field accesses
* `x.field` for arbitrary field names `field`.
*
* If a call is not natively supported by `x` (i.e. if type checking
* fails), it is rewritten according to the following rules:
*
* {{{
* foo.method("blah") ~~> foo.applyDynamic("method")("blah")
* foo.method(x = "blah") ~~> foo.applyDynamicNamed("method")(("x", "blah"))
* foo.method(x = 1, 2) ~~> foo.applyDynamicNamed("method")(("x", 1), ("", 2))
* foo.field ~~> foo.selectDynamic("field")
* foo.varia = 10 ~~> foo.updateDynamic("varia")(10)
* foo.arr(10) = 13 ~~> foo.selectDynamic("arr").update(10, 13)
* foo.arr(10) ~~> foo.applyDynamic("arr")(10)
* }}}
*
* As of Scala 2.10, defining direct or indirect subclasses of this trait
* is only possible if the language feature `dynamics` is enabled.
*/
trait Dynamic extends Any
1) applyDynamic
def applyDynamic(methodName: String)(args: Any*)
2) applyDynamicNamed与第一个不同的是可以拿到参数名称
3) 作为一个动态语言最常见的行为就是给对象赋予一个新的属性或者重新赋值,这里我们可以通过selectDynamic和updateDynamic方法做到
import scala.collection.mutable
import scala.language.dynamics
object MagicBox extends Dynamic {
private var box = mutable.Map[String, Any]()
def updateDynamic(name: String)(value: Any) { box(name) = value }
def selectDynamic(name: String) = box(name)
}
object Test extends App {
MagicBox.banana = "banana"
println(MagicBox.banana)
}