假设我有这样的ADT:
sealed trait A extends Product with Serializable
object A {
case class A1() extends A
case class A2() extends A
case class A3() extends A
case class A4() extends A
}
假设我也有trait AFoo
:
type Foo = ...
trait AFoo { def asFoo(a: A): Foo }
现在我需要为AFoo
提供两种不同的实现。所以我写的是这样的:
abstract class AFooSupport extends AFoo {
protected def asFoo1(a1: A1): Foo
protected def asFoo2(a2: A2): Foo
protected def asFoo3(a3: A3): Foo
protected def asFoo4(a4: A4): Foo
def asFoo(a: A) = a match {
case a1: A1 => asFoo1(a1)
case a2: A2 => asFoo2(a2)
case a3: A3 => asFoo3(a3)
case a4: A4 => asFoo4(a4)
}
}
class AFoo1 extends AFooSupport {
// implement asFoo1, asFoo2, asFoo3, asFoo4
}
class AFoo2 extends AFooSupport {
// implement asFoo1, asFoo2, asFoo3, asFoo4
}
这种方法可能会奏效,但我想知道是否有更好的方法。在这种情况下你会使用类型吗?
答案 0 :(得分:1)
对于具有不同实现的具体类,只有一个函数(A => Foo)
。我没有看到使用类型类的巨大优势。当其中一个参数是通用的时候,我会开始考虑一个类型。
正如评论中所建议的那样,可以将模式匹配提取到折叠
中def fold[F](a: A)(f1: A1 => F, ..., f4: A4 => F): F = a match {
case a1: A1 => f1(a1)
...
}
并实现所需的功能:
def aFoo(a: A): Foo = fold(a)(afoo1, afoo2, afoo3, afoo4)
def afoo1(a: A1): Foo = ...
...
def afoo4(a: A4): Foo = ...
def bFoo(a: A): Foo = fold(a)(bfoo1, bfoo2, bfoo3, bfoo4)
...
def bfoo4(a: A4): Foo = ...
但是你的AFooSupport
已经是使用继承而不是合成实现的折叠。
答案 1 :(得分:-2)
第一眼看来,您似乎可以使用泛型作为解决方案或通过继承来解决您的问题。