0

特定のデータ構造に適用されるルールを受け入れることができるシステムのインターフェイスを設計しています。

メインシステムは、「ルールXを引数U、V、W、...に適用する」などのコマンドを受信するドライバーとして機能することになっています。コンパイル時に考えられるすべてのルールがわからないので、引数の型情報をルール定義に埋め込んで、後で検証することを考えました。

現在、ルールの定義は次のとおりです。

trait Rule {
  val argTypes: Seq[Class[_]]
  def apply(stt: State, args: Seq[Any])
}

の実際の引数のargs数は、で定義された型の数と一致する必要がargTypesあり、メソッドapplyは操作状態を返す必要があります。(実際、これは簡単な説明ですが、これは一般的な考え方です)。

checkTypesまた、実際の引数の型がで定義された型と一致するかどうかを確認するために呼び出される関数を実装しましたargTypes

def checkTypes(args: Seq[Any]) {
  if (argTypes.size != args.size) {
    val msg = "Number of arguments (%d) does not match expected number (%d)."
    throw new IllegalArgumentException(msg.format(args.size, argTypes.size))
  }
  val err = "Incompatible argument type for [%s]. Expected: %s. Found: %s."
  for (i <- 0 until argTypes.size) {
    val formalClass = argTypes(i)
    val arg = args(i)
    val actualClass = arg.asInstanceOf[AnyRef].getClass
    if (!(formalClass isAssignableFrom actualClass)) {
      val errMsg = err.format(arg, formalClass.getName, actualClass.getName)
      throw new IllegalArgumentException(errMsg)
    }
  }
}

問題は、整数引数(コンソールまたはテキストファイルから読み取る)を渡そうとすると、checkTypesプロシージャが次のメッセージで失敗することです。java.lang.IllegalArgumentException: Incompatible argument type for [1]. Expected: int. Found: java.lang.Integer.

私は整数引数をで変換していますがInteger.parseInt(t).asInstanceOf[Int]、ルールはタイプの2つの引数を期待していますInt

それで、実行時に引数のタイプをチェックするためのより効果的な方法はありますか?

また

実際に変換Stringするにはどうすればよいですか?Int

前もって感謝します。


最小限の作業例として、これは例外を発生させるScalaREPLのセッションです。

scala> val argTypes: Seq[Class[_]] = Seq(classOf[Int], classOf[Int])
argTypes: Seq[Class[_]] = List(int, int)

scala> def checkTypes(args: Seq[Any]) {
     |   if (argTypes.size != args.size) {
     |     val msg = "Number of arguments (%d) does not match expected number (%d)."
     |     throw new IllegalArgumentException(msg.format(args.size, argTypes.size))
     |   }
     |   val err = "Incompatible argument type for [%s]. Expected: %s. Found: %s."
     |   for (i <- 0 until argTypes.size) {
     |     val formalClass = argTypes(i)
     |     val arg = args(i)
     |     val actualClass = arg.asInstanceOf[AnyRef].getClass
     |     if (!(formalClass isAssignableFrom actualClass)) {
     |       val errMsg = err.format(arg, formalClass.getName, actualClass.getName)
     |       throw new IllegalArgumentException(errMsg)
     |     }
     |   }
     | }
checkTypes: (args: Seq[Any])Unit

scala> val args: Seq[Any] = Seq("1".toInt, "2".toInt)
args: Seq[Any] = List(1, 2)

scala> checkTypes(args)
java.lang.IllegalArgumentException: Incompatible argument type for [1]. Expected: int. Found: java.lang.Integer.
    at $anonfun$checkTypes$1.apply$mcVI$sp(<console>:20)
    at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:78)
    at .checkTypes(<console>:14)
    at .<init>(<console>:11)
    at .<clinit>(<console>)
    at .<init>(<console>:11)
    at .<clinit>(<console>)
    at $print(<console>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
    at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
    at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
    at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
    at java.lang.Thread.run(Thread.java:679)
4

1 に答える 1

2

java.lang.Integerボックス化されたタイプ( )とボックス化されていないタイプ(scala.Int== java )の間に不一致がありintます。実際のインスタンスはボックス化されていますが、プリミティブclassOfに対してテストしています。

プリミティブがボックス化されたときに何が起こるかの例を次に示します。

scala> 5.getClass
res0: Class[Int] = int

scala> (5: Any)
res1: Any = 5

scala> res1.getClass
res2: Class[_] = class java.lang.Integer

パターンマッチをオンにAnyしてプリミティブを取得すると、実際にはボックス化されたコピーが選択され、ボックス化されていないことに注意してください。

scala> res1 match { case i: Int => println(i); case _ => }
5

あなたが書いたコードを考えると、あなたは箱に入れられなければならないことを知っているので、Integer代わりにチェックすることもできますInt(つまり、を使用しますclassOf[Integer])。

于 2013-02-25T00:13:03.407 に答える