【发布时间】:2017-05-17 11:03:00
【问题描述】:
假设我们有几个这样的类:
abstract class Throw {
def winsOver(t2: Throw): Boolean
}
class Rock extends Throw {
override def winsOver(t2: Throw): Boolean = t2 match {
case _: Scissors => true
case _ => false
}
}
class Scissors extends Throw {
override def winsOver(t2: Throw): Boolean = t2 match {
case _: Paper => true
case _ => false
}
}
class Paper extends Throw {
override def winsOver(t2: Throw): Boolean = t2 match {
case _: Rock => true
case _ => false
}
}
这行得通
scala>new Paper winsOver new Rock
res0: Boolean = true
scala>new Rock winsOver new Rock
res1: Boolean = false
但是,代码有很多重复。由于唯一不同的是他们击败的类型,我们可以尝试将其排除
abstract class Throw {
type Beats <: Throw
def winsOver(t2: Throw): Boolean = t2 match {
case _: Beats => true
case _ => false
}
}
class Rock {
type Beats = Scissors
}
class Scissors {
type Beats = Paper
}
class Paper {
type Beats = Rock
}
但是编译器开始抱怨
warning: abstract type pattern Throw.this.Beats is unchecked since it is eliminated by erasure
case _: Beats => true
果然,它不起作用。 winsOver 突然总是返回 true
scala>new Rock winsOver new Rock
res0: Boolean = true
我一直试图弄清楚这一点,并且根据我的发现,这是因为 JVM 没有携带尽可能多的类型信息。这会导致一些信息丢失(“擦除”),并且有一些方法可以在 scala 中解决这个问题,以前使用清单,现在使用类标签和类型标签。
我真的无法更具体地弄清楚它是如何工作的,虽然我有时能够从互联网上复制代码 sn-ps 来做类似的事情,但我并不真正理解该代码是如何工作的我无法适应这个例子。我还注意到有一个无形库对这种东西有很多支持,但我也想了解它是如何工作的。
【问题讨论】: