К сожалению, это неотъемлемое ограничение asInstanceOf
. Я действительно удивлен, увидев, что скародок упомянул это в подробностях :
Обратите внимание, что успех приведения во время выполнения - это семантика стирания по модулю Скалы. Поэтому выражение 1.asInstanceOf[String]
будет выбрасывать ClassCastException
во время выполнения, в то время как выражение List(1).asInstanceOf[List[String]]
не будет. В последнем примере, поскольку аргумент типа удаляется как часть компиляции, невозможно проверить, принадлежит ли содержимое списка запрошенному типу.
Если вы в основном обеспокоены неудачным быстрым при неверном приведении для traversable, что, вероятно, будет основной проблемой при возврате содержимого из вашего интерфейса DB / memcached, я пытался навязать приведение головы к перемещаемым объектам:
def failFastCast[A: Manifest, T[A] <: Traversable[A]](as: T[A], any: Any) = {
val res = any.asInstanceOf[T[A]]
if (res.isEmpty) res
else {
manifest[A].newArray(1).update(0, res.head) // force exception on wrong type
res
}
}
На простом примере это работает:
scala> val x = List(1, 2, 3): Any
x: Any = List(1, 2, 3)
scala> failFastCast(List[String](), x)
java.lang.ArrayStoreException: java.lang.Integer
[...]
scala> failFastCast(List[Int](), x)
res22: List[Int] = List(1, 2, 3)
Но не на более сложном:
val x = Map(1 -> ("s" -> 1L)): Any
failFastCast(Map[Int, (String, String)](), x) // no throw
Интересно, есть ли способ рекурсивного углубления в A, чтобы продолжить приведение, пока нет больше параметров типа ...