我需要通过界面传递函数,该界面会删除类似actor' s receive
方法的类型。所以我想存储已擦除的类型参数并使用它来构建参数。
class Store[R,T](val action : R => T)(implicit i : TypeTag[R], o : TypeTag[T]) {
val in : Type = i.tpe
val out : Type = o.tpe
}
object Store {
type Any = Store[_,_]
def apply[R,T](action : R => T)(implicit i : TypeTag[R], o : TypeTag[T]) : Store[R,T] = new Store(action)
}
final case class Box[T](unbox : T)
def getType[T](x : T)(implicit t : TypeTag[T]) : Type = t.tpe
val source = Box("test")
val x = Store[Box[String], Box[Int]](s => Box(s.unbox.length))
val y = Store[Box[Int], Box[Boolean]](i => Box(i.unbox % 3 == 0))
val all : List[Store.Any] = List(x,y)
val a0 = all(0)
val a1 = all(1)
我希望将存储的操作链接起来:
val c0 = a0.action(source)
val c1 = a1.action(c0)
显然失败了:
error: type mismatch;
found : source.type (with underlying type Box[String])
required: _$1
val c0 = a0.action(source)
^
one error found
我可以在运行时检查所有类型是否匹配:
assert(getType(source) <:< a0.in)
assert(a0.out <:< a1.in)
但是我怎样才能将参数转换为适当的类型呢? asInstanceOf
需要编译时类型,而不是运行时反射。还有哪些其他技巧?
答案 0 :(得分:1)
一种方法是使用ClassTag[T]
及其unapply
方法:
def castIfPossible[T](object: Any)(implicit tag: ClassTag[T]): Option[T] =
tag.unapply(object)
如果object
属于T
类型,则会收到Some[T]
值,否则您将收到None
。
然后,您需要在代码中执行的操作是假设类型始终匹配(但之后您可能不需要反射)或使用某些map
或{ {1}}用于将值组合在一起。
就个人而言,我会试着弄清楚是否可以完全取消反射,好像T会被参数化,然后反射不会检查这些参数是否匹配。然后我会使用类型类来处理问题。但是,我知道它可能并不总是可能的。