我知道我可以这样写:
case class Something[T <: Foo with Bar](state: T)
这接受具有特征(或类和特征)Foo
和Bar
的类。这是一个AND示例,需要扩展Foo
和Bar
。是否有一个选项允许我传递扩展Foo
或Bar
的类以模式匹配它们?
用例是我有多个具有不同行为的类,它们使用共享类型的状态:
trait FooState
trait BarState
trait BazState
case class Foo(state: FooState) // must not accept BarState or BazState
case class Bar(state: BarState) // must not accept FooState or BazState
case class Baz(state: BazState) // must not accept FooState or BarState
case class FooBar(state: FooState or BarState) // must not accept BazState
case class FooBaz(state: FooState or BazState) // must not accept BarState
case class BarBaz(state: BarState or BazState) // must not accept FooState
我知道我可以为每个复合类创建另一个特征,但这会迫使我将它添加到扩展任何这些先前特征的所有内容中。
答案 0 :(得分:3)
是的,你通常会使用类型类来实现你想要的,以及一个上下文绑定。以下是:
trait Acceptable
object Acceptable {
implicit val fooIsGood = new Acceptable[Foo] {}
implicit val barIsGood = new Acceptable[Bar] {}
}
case class Something[T : Acceptable](state: T)
您可以使用它来实现使用此模式所需的任何功能。使用Either
或联合产品实现真正的联合类型绑定,但在大多数情况下,这可能更简单。
答案 1 :(得分:1)
一种可能的方法是使用Either
类型:
case class FooBar(state: Either[FooState, BarState]) {
def someOperation() = {
state match {
case Left(fooState) => ???
case Right(barState) => ???
}
}
}
您所描述的是一种工会类型。 Scala的当前版本不支持它们,因为您已经对它们进行了描述,但是它计划用于Dotty。
如果您需要更多的灵活性(例如,超过两种类型),请考虑使用函数式编程库中的Coproduct。 Scalaz,Cats和Shapeless都暴露了它们。