标签:
从Scala 2.10 开始,增加了Dynamic类型,所有直接或间接的继承自 Dynamic 的类,都可以实现。
Dynamic 继承自 Any,它的源代码中什么都没有,只有一句话。
trait Dynamic extends Any
按照官方的描述,Dynamic 是一个运行动态执行的 trait 标识,它没有成员,具体的实现由编译器嵌入,它可以动态的执行任意名字的方法或参数。这个怎么理解呢,我姑且认为它是动态产生方法和字段吧。
要想使用Dynamic ,需要打开编译器选项 -language:dynamics 或者 导入包:
import scala.language.dynamics
Dynamic 的操作都会经过下面四个方法
下面我们定义一个类,继承自Dynamic
class DynamicPerson extends Dynamic{
def selectDynamic(key:String) = s"你要执行的是:$key"
}
先实现一个selectDynamic,看看它的使用
下面的代码,可以认为动态生成一个 Name方法,结果是一个字符串。
val person = new DynamicPerson()
person.Name //定以后Name后,后面的代码中就可以访问Name了
/**
我们还可以增加其它的方法
person.Age
person.Address
*/
println(person.Name) // 输出结果 :"你要执行的是:Name"
那其实为了更清晰,我们更倾向于在DynamicPerson内部维护一个Map,里面可以保存属性和属性的值,或者是方法名和方法的引用,看下面的类:
import scala.language.dynamics
class DynamicPerson extends Dynamic{
private val fields =mutable.HashMap.empty[String,Any].withDefault{ key => throw new NoSuchFieldError(key) }
//获取key对应的value值
def selectDynamic(key:String) = fields(key)
//更新key对应的value值
def updateDynamic(key: String)(args: Any): Unit ={
fields(key) = args;
}
}
下面是使用,用起来很方便,不用关心里面的Map,就好像定义和访问属性一样
val person = new DynamicPerson()
person.Age = 30
person.Name = "Mike"
//上面对 Age 和 Name 的赋值操作,就是通过 updateDynamic 完成的
println("%s年龄是%d".format(person.Name,person.Age))
/**
Mike年龄是30
*/
上面是属性的操作,那下面看看如何进行方法的操作,我们需要用到applyDynamic,定义下面的类
import scala.language.dynamics
class DynamicPerson extends Dynamic{
//定义一个方法类型 CallFun,它接收 Int 类型参数,并返回 String 类型 ,这个有点像 C# 中的 delegate
type CallFun = Int => String
//Map对象,存放属性
private val fields =mutable.HashMap.empty[String,Any].withDefault{ key => throw new NoSuchFieldError(key) }
//Map对象,存放方法对象
private val functions =mutable.HashMap.empty[String,CallFun].withDefault{ key => throw new NoSuchFieldError(key) }
//选取对象
def selectDynamic(key:String) = fields(key)
/**
更新key对应的value
这里做了一个判断,如果key以call字符串开头,我们认为是args是CallFun类型
*/
def updateDynamic(key: String)(args: Any): Unit ={
args match {
case x if key.startsWith("call") => functions(key) = x.asInstanceOf[CallFun]
case _ => fields(key) = args
}
}
//这个就是用来动态执行方法的
def applyDynamic(key: String)(arg:Int) = {
println(functions(key)(arg))
}
}
使用
val person = new DynamicPerson()
//设置Name属性
person.Name = "Mike"
//定义一个 call 方法
person.call = (age:Int) => s"${person.Name} 今年 $age 岁"
//通过 applyDynamic 执行 call 方法
person.call(80) //这句代码将打印出:"Mike 今年 80 岁"
标签:
原文地址:http://blog.csdn.net/bdmh/article/details/50147301