【问题标题】:How to use functions when their types are erased?擦除类型时如何使用函数?
【发布时间】:2017-02-14 16:12:58
【问题描述】:

我需要通过删除类型的接口传递函数,例如演员的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 需要编译时类型,而不是运行时反射。还有哪些技巧可用?

【问题讨论】:

    标签: scala type-erasure dynamic-cast


    【解决方案1】:

    一种方法是使用ClassTag[T] 及其unapply 方法:

    def castIfPossible[T](object: Any)(implicit tag: ClassTag[T]): Option[T] =
      tag.unapply(object)
    

    如果objectT 类型,您将收到Some[T] 值,否则您将收到None

    那么你需要在你的代码中做的事情就是假设类型总是匹配的(但你可能不需要反射)或者使用一些mapflatMap将值组合在一起.

    就个人而言,我会尝试弄清楚是否可以完全取消反射,好像 T 将被参数化,然后反射不会检查这些参数是否匹配。然后我会使用类型类之类的东西来处理这个问题。但是,我知道这可能并不总是可行的。

    【讨论】:

    • ClassTag[T] 要求保留类型T。 >要么假设类型总是匹配的type classesAny 类型的接口,那么您所能做的就是运行时模式匹配
    • 在某些时候,您知道 T 的类型 - 这是您可以创建 ClassTag 并将其传递给忘记它的代码部分的时候 - 除非您真的无法控制在访问对象之前覆盖对象并且类型已经丢失。至于保持T 的类型 - 不一定。在某些时候,您可能会开始使用存在类型。那么 T 可以在 class SomeTHandler[T](value: T)(implicit tag: ClassTag[T]) 内部知道,但在接口级别上是 horgot:SomeHanlderT[_]
    • 你怎么能猜到SomeHandlerT[_]应该在类型已经被删除时返回Option[T]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    相关资源
    最近更新 更多