我在挖掘新 2.10 版本的 Scala(有点稀疏?)文档时遇到了麻烦。我有一种情况,我从没有类型信息的源递归地读取数据。在阅读时,我知道预期的类型,因此我可以检查该类型是否与传入的数据一致。
我的问题是:当尝试使用类型参数(例如 an Array[Int]
)检索集合对象时,如何使用预期的类型来确保读取的值是正确的类型?
到目前为止,我已经摆弄了Scala Api提供的允许您提取类型参数的代码。我还阅读了有关类标签以及如何使用它们来创建数组的信息。所以我的下一个想法是 1)找到类型参数,2)从该类型创建一个数组,3)查看读取的数据是否适合无异常,如下所示:
val paramType = paramInfo[Array[X]] // Step 1: Find the X type parameter
val array = Array[paramType](size) // Step 2: Can't use TypeTags#Type as a normal Java type...
// Step 3: Feed data into the array and hope for the best
// Step 4: Profit!
由于上面paramType
给了我类型,将类型转换为类标记应该很简单。但答案让我感到困惑。
老实说,这个解决方案对我来说似乎有点混乱,但我还没有找到更聪明的办法。如果有其他解决方案,我会全力以赴!
提前致谢。
编辑:为了澄清,我上面的例子应该证明我想从 Array[Int] 中提取类型 X (例如),然后创建一个包含该特定类型的数组的实例。希望这更清楚。
编辑:也许需要进一步澄清(我真的让它不清楚吗?:-))。我想从数据源中读取一个集合。我希望使用正确的、预期的类型键入该集合。所以假设我调用方法readData
。因为我知道预期的类型,所以我给它一个预期类型的类型参数。例如,假设 Array[Int]。它可以是 Array[String] 或 Iterable[Any] 或只是 Null 或其他。当。。。的时候readData
方法被调用时,我想将给定的预期类型 (Array[Int]) 与从外部源读取的数据的类型相匹配。如果找到的类型与我们期望的类型相同或子类型,则可以转换并返回数据。如果不是,则抛出异常,通知用户找到的数据不是预期的类型。所以总结一下:我如何打电话readData[Array[Int]]
上班?
编辑:我通过创建 Array[Any] 解决了这个问题,检索预期类型(上面的 X)并迭代数组以查看元素是否与 X 的类型(或子类型)相同。如果是,我们可以安全地转换为数组 [X]。在下面的示例中,预期的类型由 E 表示。我知道这很 hackish,但同样:我很乐意看到替代方案......
// Matches if the type of o corresponds (<:<) to the type of x
def verifyType(o : Any, x : Type) : Boolean = { ... }
// Get the type of the array parameter (X)
val tpe = reflect.runtime.universe.typeOf[E] tpe match {
// The returned Type is not an instance of universe.Type - hence the cast
case TypeRef(_, _, args) => args.asInstanceOf[List[Type]]
case _ => throw new IllegalArgumentException("Could not find type parameters in type " + tpe)
}
// Iterate the array and make sure the types match
val hasWrongType = array.exists(e => !verifyType(e, tpe))
if (hasWrongType) throw new Exception(...) // The types does not fit
else array.asInstanceOf[E] // We can safely cast