我想要构建一个对
所以我试了一下,但结果让我失望了。
isInstanceOf[T]
和 asInstanceOf[T]
进行包装的容器,它会输出 Option[T]
并提供方便的 map
和 getOrElse
方法。所以我试了一下,但结果让我失望了。
import scala.reflect.runtime.universe.{TypeTag, typeOf}
class Base()
class Deep() extends Base
class Deeper() extends Deep()
final case class WrapSimple[T](source : T) {
def cast[U] : Option[U] =
if (source.isInstanceOf[U]) Some(source.asInstanceOf[U]) else None
}
final case class WrapFullTagged[T: TypeTag](source : T) {
def cast[U : TypeTag] : Option[U] =
if (typeOf[T] <:< typeOf[U]) Some(source.asInstanceOf[U]) else None
}
final case class WrapHalfTagged[T](source : T) {
val stpe = {
val clazz = source.getClass
val mirror = scala.reflect.runtime.universe.runtimeMirror(clazz.getClassLoader)
mirror.classSymbol(clazz).toType
}
def cast[U : TypeTag] : Option[U] =
if (stpe <:< typeOf[U]) Some(source.asInstanceOf[U]) else None
}
object Test {
val base = new Base
val deep = new Deep
val deeper = new Deeper
val wile : Deep = new Deeper
def testSimple() : Unit = {
println(WrapSimple(deep).cast[Base].isDefined) // should be true
println(WrapSimple(deep).cast[Deeper].isDefined) // should be false
println(WrapSimple(wile).cast[Deeper].isDefined) // should be true
}
def testFullTagged() : Unit = {
println(WrapFullTagged(deep).cast[Base].isDefined) // should be true
println(WrapFullTagged(deep).cast[Deeper].isDefined) // should be false
println(WrapFullTagged(wile).cast[Deeper].isDefined) // should be true
}
def testHalfTagged() : Unit = {
println(WrapHalfTagged(deep).cast[Base].isDefined) // should be true
println(WrapHalfTagged(deep).cast[Deeper].isDefined) // should be false
println(WrapHalfTagged(wile).cast[Deeper].isDefined) // should be true
}
def testAll() : Unit = {
testSimple()
testFullTagged()
testHalfTagged()
}
}
WrapSimple
看起来不错,但它无法正常工作,它会擦除 isInstanceOf[U]
方法中的 U
类型,因此它总是返回 true
。有趣的是,asInstanceOf[U]
通常会保留 U
类型,所以它只会产生运行时异常。
我尝试过的第二种方法是使用类型标签的 WrapFullTagged
。它似乎很清晰,但同样违反了契约。它只能在编译时检查静态类型,并且对运行时实际类型没有任何了解。
因此,我结合了两种方法,产生了第三种方法,至少能够产生正确的输出。但它看起来很糟糕,并调用了具有巨大代价的反射功能。
是否可能以更高雅的方式解决这个问题?
TypeTag
在编译时保留它,则可以在运行时拥有所有类型信息的唯一方法。在第一个示例中,T
和U
都被擦除了。您能否命名一个使用案例,其中WrapFullTagged
不能提供所需的结果? - Michael ZajacisInstanceOf
时,这通常发生在您不知道运行时变量背后的实际类型时。这种情况经常发生。您可以尝试回忆一下上次编写没有任何模式匹配的项目是什么时候。 - ayvango