Я пытаюсь реализовать что-то, что фактически является перечислением в Scala.Я хотел бы сделать это, используя классы case, чтобы компилятор мог обнаруживать любые неисчерпывающие совпадения с образцами.
Это прекрасно работает в самой базовой форме, например:
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 => ...
...
}
Однако это не идеально, поскольку имена объектов case могут легко конфликтовать:
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
Очевидное решение - поместить объекты case в отдельные пространства имен:
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
}
Это имеет смысл, так как «Левый» в данном случае является экземпляром, а не типом, и я подозреваю, что есть простой способ ссылки на тип.Самое близкое к этому достижение, которое я мог бы получить, это:
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 является типом, а не объектом, и поэтому невозможно ссылаться на один из вложенных объектов с помощью доступа к полю, а, с другой стороны, эти объекты не являются типами, поэтому невозможно ссылаться на них с помощьюСимвол «#».
Можно ли ссылаться на объекты, вложенные в класс, за пределами этого класса?
EDIT
До сих пор я обнаружил, что объекты пакета являются лучшим способом решения этой проблемы.
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)
}
Однако, вопрос выше (доступвложенных объектов в классах) до сих пор стоит.