码迷,mamicode.com
首页 > 其他好文 > 详细

Scala:Dynamic

时间:2015-12-03 09:55:32      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:

Scala开篇(目录)

从Scala 2.10 开始,增加了Dynamic类型,所有直接或间接的继承自 Dynamic 的类,都可以实现。
Dynamic 继承自 Any,它的源代码中什么都没有,只有一句话。

trait Dynamic extends Any

按照官方的描述,Dynamic 是一个运行动态执行的 trait 标识,它没有成员,具体的实现由编译器嵌入,它可以动态的执行任意名字的方法或参数。这个怎么理解呢,我姑且认为它是动态产生方法和字段吧。
要想使用Dynamic ,需要打开编译器选项 -language:dynamics 或者 导入包:

import scala.language.dynamics

Dynamic 的操作都会经过下面四个方法

  1. selectDynamic:创建字段或方法
  2. updateDynamic:更新字段或方法
  3. applyDynamic:执行方法,可以带参数
  4. applyDynamicNamed:执行方法,参数可以指定名称

下面我们定义一个类,继承自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 岁"

Scala:Dynamic

标签:

原文地址:http://blog.csdn.net/bdmh/article/details/50147301

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!