4

コマンドデザインパターンを実装するクラスを作成しました。

class MyCommand[-T, +R](val name: String, val execute: T => R)

、2つのコマンドを準備し、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)

次に、実行する2つのデータがあります。

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

助けて :(

4

1 に答える 1

2

この問題を解決するためのより良い方法があると確信していますが、これはうまくいくかもしれません。Scala 2.9.2 でテストしました。

MyCommand追加の暗黙の引数としてaを受け取ります。これにより、実行時に関数Manifestの from 型を表すクラスにアクセスできます。execute

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
于 2012-08-05T12:54:50.217 に答える