在Scala中运行时检查参数类型(来自可变长度参数列表)
我正在为一个系统设计接口,该系统可以接受应用于给定数据结构的规则 主系统被认为是一个接收命令的驱动程序,比如“将规则X应用于参数U、V、W,…”。我在编译时不知道所有可能的规则,所以我想在规则定义中嵌入参数类型信息,然后验证它 目前规则定义如下:在Scala中运行时检查参数类型(来自可变长度参数列表),scala,variadic-functions,runtime-type,Scala,Variadic Functions,Runtime Type,我正在为一个系统设计接口,该系统可以接受应用于给定数据结构的规则 主系统被认为是一个接收命令的驱动程序,比如“将规则X应用于参数U、V、W,…”。我在编译时不知道所有可能的规则,所以我想在规则定义中嵌入参数类型信息,然后验证它 目前规则定义如下: trait Rule { val argTypes: Seq[Class[_]] def apply(stt: State, args: Seq[Any]) } args中的实际参数数量必须与argTypes中定义的类型数量匹配,并且方法ap
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)
}
}
}
装箱类型(
java.lang.Integer
)与未装箱类型(scala.Int
==javaInt
)不匹配。实际的实例是装箱的,但是您要针对的是原始类
下面是装箱基本体时发生的情况的示例:
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]
)。@RexKerr实际上我不知道可以直接在字符串上调用toInt
,但是,即使在做了您建议的更改之后,我仍然会收到相同的错误。谢谢您的帮助,但我仍然不确定什么是解决我的问题的最佳方法。将argTypes
的声明更改为使用classOf[Integer]
而不是classOf[Int]
?
scala> res1 match { case i: Int => println(i); case _ => }
5