TypeTag用于包含抽象类型的类型

时间:2014-06-22 07:29:15

标签: scala abstract-type

我们有一个特征Foo,正在考虑一个方法cast,它采用类型参数A <: Foo和参数f: Foo,如果{Some(f: A)则返回f <: A {1}},否则None

trait Foo
def cast[A <: Foo](f: Foo): Option[A] = ???

如果Foo扩展永远不会是通用的,那么附加ClassTag就是结论:

def cast[A <: Foo : ClassTag](f: Foo) = f match {
  case f: A => Some(f)
  case _ => None
}
...
class Bar extends Foo
class Hoo extends Foo
println cast[Bar](new Bar) //→ Some(Bar)
println cast[Hoo](new Bar) //→ None

但是如果存在一些带有抽象类型的Foo怎么办?如:

trait FooTyped extends Foo {
  type T
}

然后cast根本就被破坏了:

type FooT[A] = FooTyped{ type T = A }
...
val fint: FooT[Int] = new FooTyped{ type T = Int }
println cast[FooT[String]](fint) //→ Some(FooTyped) OH WHAT?

这是因为ClassTag不关心类型参数和抽象类型。

所以我们将使用跟踪它们的TypeTag ...但我不确切知道如何。

请帮我写完这篇文章:(

2 个答案:

答案 0 :(得分:2)

有:

trait Foo
def cast[A <: Foo](f: Foo): Option[A] = ???

对于值TypeTag,您不仅需要A目标类型TypeTag,还需要f。 JVM中的对象在运行时不携带完整类型信息。

答案 1 :(得分:2)

ghik回答是正确的。作为补充,我提供了一种可能的方法来实现这一目标:

使用此助手类:

class Caster[B : TypeTag](f: B) {
  def cast[A <: Foo : TypeTag] = 
    if(typeOf[B] <:< typeOf[A]) Some(f) else None
}

你会得到这样的预期答案:

println(new Caster(new Bar).cast[Bar]) //→ Some(Bar)
println(new Caster(new Bar).cast[Hoo]) //→ None
println(new Caster(fint).cast[FooT[String]]) //→ None