Scala Enumerations中的错误(?)类型匹配

时间:2011-10-21 12:08:19

标签: scala enumeration

我有一个用于表示值类型的枚举类。该类的代码非常简单:

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

另外,我怎样才能避免这种怪异?如何从值中进行类型匹配以区分不同的枚举?

1 个答案:

答案 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的结果。