Valid type casting of both covariant and contravariant class at runtime in Scala

只谈情不闲聊 提交于 2019-12-05 17:45:27

I am pretty sure that there are better ways of solving this problem, but this might work for you. I tested it with Scala 2.9.2.

MyCommand takes a Manifest as an additional implicit argument, which gives us access to the class that represents the from-type of the execute function at runtime:

class MyCommand[-T: Manifest, +R](val name: String, val execute: T => R) {
  val fromClass = manifest[T].erasure
}

The list of commands is basically as in your original post, as is the list of data:

val commands = List(
  new MyCommand[String, String]("lower", _.toLowerCase()),
  new MyCommand[Date, Long]("time", _.getTime)
)

val data = List("StRiNG", new Date())

Matching data to commands relies on the runtime representation of the involved types as classes, and a rather ugly cast. The cast is especially ugly because it does not give a precise return type, i.e., additional matches or casts are necessary if you need to know the precise return type of the command's return value.

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))
    }
  }
}

The output is:

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!