我写了一个实现command design pattern的课程:
class MyCommand[-T, +R](val name: String, val execute: T => R)
,准备了两个命令并将其存储在MutableList中:
val commands = new mutable.MutableList[MyCommand[Nothing, Any]]
commands += new MyCommand[String, String]("lower", s => s.toLowerCase())
commands += new MyCommand[Date, Long]("time", d => d.getTime)
然后我要执行两个数据:
val data = Array("StRiNG", new Date())
对我来说问题是我不知道如何确定哪个数据适用于该命令:
data.foreach {
d => commands.foreach {
c =>
// println(c.execute(d)) if d is applicable to c.execute().
}
}
我尝试的是模式匹配与类型规范,但它产生语法错误:
c.execute match {
case m: (d.getClass => Any) => println(c.execute(d))
}
帮助我:(
答案 0 :(得分:2)
我很确定有更好的方法来解决这个问题,但这可能适合你。我用Scala 2.9.2测试了它。
MyCommand
将Manifest
作为附加的隐式参数,这使我们可以访问在运行时表示execute
函数的from-type的类:
class MyCommand[-T: Manifest, +R](val name: String, val execute: T => R) {
val fromClass = manifest[T].erasure
}
命令列表与原始帖子基本相同,数据列表也是如此:
val commands = List(
new MyCommand[String, String]("lower", _.toLowerCase()),
new MyCommand[Date, Long]("time", _.getTime)
)
val data = List("StRiNG", new Date())
将数据与命令匹配依赖于所涉及类型的运行时表示形式,以及相当丑陋的演员表。演员阵容特别难看,因为它没有给出精确的返回类型,例如,如果您需要知道命令返回值的精确返回类型,则需要额外的匹配或强制转换。
data foreach { d =>
commands foreach { c =>
println("data: %s (%s), command takes: %s"
.format(d, d.getClass.getSimpleName, c.fromClass.getSimpleName))
if (d.getClass.isAssignableFrom(c.fromClass)) {
println(" cmd(data) = " + c.execute.asInstanceOf[Any => Any](d))
}
}
}
输出结果为:
data: StRiNG (String), command takes: String
cmd(data) = string
data: StRiNG (String), command takes: Date
data: Sun Aug 05 14:46:17 CEST 2012 (Date), command takes: String
data: Sun Aug 05 14:46:17 CEST 2012 (Date), command takes: Date
cmd(data) = 1344170777681