我正在尝试实现一些在 Scala 中实际上是枚举的东西。我想使用案例类来做到这一点,以便编译器能够检测到任何非详尽的模式匹配。
这在非常基本的形式下工作正常,例如:
sealed abstract class HorizontalAlignment
case object Left extends HorizontalAlignment
case object Right extends HorizontalAlignment
case object Center extends HorizontalAlignment
case object AsIs extends HorizontalAlignment
...
def test (x : HorizontalAlignment) =
x match {
case Left => ...
...
}
然而,这并不理想,因为案例对象的名称很容易发生冲突:
sealed abstract class HorizontalAlignment
case object Left extends HorizontalAlignment
case object Right extends HorizontalAlignment
case object Center extends HorizontalAlignment
case object AsIs extends HorizontalAlignment
sealed abstract class VerticalAlignment
case object Top extends VerticalAlignment
case object Bottom extends VerticalAlignment
case object Center extends VerticalAlignment
case object AsIs extends VerticalAlignment
// "Center" and "AsIs" clash
显而易见的解决方案是将案例对象放入单独的命名空间中:
sealed abstract class HorizontalAlignment {
case object Left extends HorizontalAlignment
case object Right extends HorizontalAlignment
case object Center extends HorizontalAlignment
case object AsIs extends HorizontalAlignment
}
sealed abstract class VerticalAlignment {
case object Top extends VerticalAlignment
case object Bottom extends VerticalAlignment
case object Center extends VerticalAlignment
case object AsIs extends VerticalAlignment
}
但是如何在匹配块中引用这些类?
它们不能用 Java 样式的点来引用:
def test (x : HorizontalAlignment) =
x match {
case HorizontalAlignment.Left => 0 // error: not found: value HorizontalAlignment
}
“#”符号似乎也不起作用:
def test (x : HorizontalAlignment) =
x match {
case HorizontalAlignment#Left => 0 // error: '=>' expected but '#' found
}
这种形式也不起作用:
def test (x : HorizontalAlignment) =
x match {
case _ : HorizontalAlignment#Left => 0 // error: type Left is not a member of Test.HorizontalAlignment
}
这是有道理的,因为在这种情况下“Left”是一个实例而不是一个类型,我怀疑有一种简单的方法来引用该类型。我能达到的最接近的目标是:
sealed abstract class HorizontalAlignment {
case class Left extends HorizontalAlignment
case class Right extends HorizontalAlignment
case class Center extends HorizontalAlignment
case class AsIs extends HorizontalAlignment
object Left
object Right
object Center
object AsIs
}
但是虽然这使得匹配块编译得很好,但我找不到任何方法来实际引用这些对象,例如将这个“枚举”的成员传递给函数。这是因为 HorizontalAlignment 是一种类型而不是对象,因此无法使用字段访问来引用其中一个嵌套对象,另一方面,这些对象不是类型,因此无法使用“#“ 象征。
有没有办法从该类外部引用嵌套在该类中的对象?
编辑
到目前为止,我发现包对象是解决这个问题的最好方法。
package object HorizontalAlignment {
sealed abstract class HorizontalAlignment
case object Left extends HorizontalAlignment
case object Right extends HorizontalAlignment
case object Center extends HorizontalAlignment
case object AsIs extends HorizontalAlignment
}
package object VerticalAlignment {
sealed abstract class VerticalAlignment
case object Top extends VerticalAlignment
case object Bottom extends VerticalAlignment
case object Center extends VerticalAlignment
case object AsIs extends VerticalAlignment
}
object Test {
import HorizontalAlignment.HorizontalAlignment
import VerticalAlignment.VerticalAlignment
def test (x : HorizontalAlignment, y : VerticalAlignment) = {
x match {
case HorizontalAlignment.Left => ...
...
}
y match {
case VerticalAlignment.Top => ...
...
}
}
def testTest = test (HorizongalAlignment.Left, VerticalAlignment.Top)
}
但是,上述问题(访问类中的嵌套对象)仍然存在。