【问题标题】:Valid type casting of both covariant and contravariant class at runtime in ScalaScala 运行时协变和逆变类的有效类型转换
【发布时间】:2012-08-02 16:38:59
【问题描述】:

我写了一个实现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))
}

帮帮我:(

【问题讨论】:

  • 请说明您的具体问题。你想做什么?
  • 我提出了一个实际上并没有像我预期的那样工作的解决方案。你能澄清数据的来源吗?我认为当您需要使用 Nothing 时,会发生一些非常奇怪的事情:)

标签: scala types covariance contravariance


【解决方案1】:

我很确定有更好的方法来解决这个问题,但这可能对你有用。我用 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

【讨论】:

  • 太棒了!我没有考虑过使用 Manifest。它完美无缺!谢谢。
猜你喜欢
  • 2013-11-29
  • 2020-01-25
  • 2015-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多