儿童特质的用处?

时间:2015-07-25 16:32:31

标签: scala traits

以下功能有一般或特定错误。

scala> trait Error
defined trait Error

scala> case object General extends Error
defined object General

scala> trait FooError extends Error
defined trait FooError

scala> case object FooError42 extends FooError
defined object FooError42

然后,有两个功能:

scala> def f: Either[Error, Int] = Right(42)
f: Either[Error,Int]

scala> def h: Either[FooError, Int] = Right(55)
h: Either[FooError,Int]

最后,我们可以使用for-understanding来链接它们:

scala> for { 
     |  a <- f.right
     |  b <- g.right
     | } yield b
res3: scala.util.Either[Error,Int] = Left(FooError42)

在这种情况下,Left的返回类型为Error,因为Error可能会出现FooErrorLeft。有必要使用Error,因为此类型可以表达ErrorFooError孩子的孩子。

进一步将Error专门化为FooError是否有用,即使for-comprehension返回Either[Error, Int]

换句话说,即使trait未使用直接,创建Error的孩子FooError是否有用?

1 个答案:

答案 0 :(得分:1)

在你琐碎的例子中,FooError似乎是多余的。特别是, 它不清楚为什么General与可能扩展FooError的各种其他对象/类有意义地不同。所以我从设计中消除了后者。

一旦你有一些有元数据的错误(比如错误代码),但有一些没有,你会更有意义,你需要以不同的方式处理这两种情况。然后,您可以将前者收集到特征中并在特征中声明错误代码:

trait FooError extends Error {
  def rc: Int
}

object FooError42 extends FooError {
  val rc = 42
}

然而,通过将特征转化为抽象或案例类,可以更好地处理大量的样板,如下所示:

trait Error
object General extends Error
case class FooError (rc: Int) extends Error
object FooError42 extends FooError(42)
object NotFoundError extends FooError(404)

然后使用案例类也可以使模式匹配代码更简单:

def report(e: Error): String = e match {
  case FooError(rc) => "HTTP error " + rc
  case General      => "Complete and utter failure"
}