我有一个用于表示值类型的枚举类。该类的代码非常简单:
object Type extends Enumeration {
type Type = Value
val tInt, tBoolean, tString, tColor, tFont, tHAlign, tVAlign, tTextStyle, tUnknown = Value;
def fromValue (value:Any) : Type.Type = {
value match {
case a:Int => tInt
case a:Boolean => tBoolean
case a:Color => tColor
case a:Font => tFont
case a:HAlign.HAlign => tHAlign
case a:VAlign.VAlign => tVAlign
case a:TextStyle.TextStyle => tTextStyle
case _ => tUnknown
}
}
}
我有哪些枚举:
object VAlign extends Enumeration {
type VAlign = Value
val top, middle, bottom = Value
}
object HAlign extends Enumeration {
type HAlign = Value
val left, center, right = Value
}
object TextStyle extends Enumeration {
type TextStyle = Value
val bold, italic, regular = Value
}
那么,为什么会出现以下奇怪之处?:
scala> Type fromValue VAlign.bottom
res3: Type.Type = tHAlign
另外,我怎样才能避免这种怪异?如何从值中进行类型匹配以区分不同的枚举?
答案 0 :(得分:7)
我相信你面临着一个擦除路径依赖类型的问题(另见下面的编辑2)。
让我们先简化一下这个例子:
object Enum1 extends Enumeration {
val A, B = Value
}
object Enum2 extends Enumeration {
val C, D = Value
}
def t(x : Any) {
println(x match {
case ab : Enum1.Value => "from first enum"
case cd : Enum2.Value => "from second enum"
case _ => "other"
})
}
现在,与您观察到的类似,t(Enum1.A)
和t(Enum2.C)
都打印"from first enum"
。
什么 - 我原本以为(请参阅下面的编辑) - 这里发生的是,在模式中使用instanceOf
导致的:
测试不会在两个路径之间产生差异 - 依赖于Value
的实例化,因此第一种情况总是匹配。
解决此问题的一种方法是匹配枚举的值而不是这些值的类型:
def t2(x : Any) {
println(x match {
case Enum1.A | Enum1.B => "from first enum"
case Enum2.C | Enum2.D => "from second enum"
case _ => "other"
})
}
编辑1 实际上我的假设与spec所说的不符。根据语言规范(§8.2类型模式):
类型模式由类型,类型变量和通配符组成。一种 模式T具有以下形式之一:
- 对C类,p.C或T #C的引用。此类型模式匹配给定类的任何非null实例。请注意前提 如果给出,该课程与确定课程相关 实例。例如,模式p.C仅匹配的实例 使用路径p创建的类C作为pre fi x。底部 类型scala.Nothing和scala.Null不能用作类型模式, 因为在任何情况下它们都不匹配。
- [...]
如果我理解正确,instanceOf
或等效的应区分这两种情况。
编辑2 似乎是this issue的结果。