如何在Scala自定义异常中设置消息?

如何在Scala自定义异常中设置消息?,scala,exception,exception-handling,Scala,Exception,Exception Handling,我有以下特点: trait ServiceException extends Exception { val message: String val nestedException: Throwable } 例外情况如下所示: case class NoElementFoundException(message: String = "error.NoElementFoundException", ne

我有以下特点:

trait ServiceException extends Exception {

  val message: String

  val nestedException: Throwable

}
例外情况如下所示:

case class NoElementFoundException(message: String = "error.NoElementFoundException",
                                        nestedException: Throwable = null) extends ServiceException
def bla(exception: Throwable) = exception.getMessage
问题是如果我有这样的方法:

case class NoElementFoundException(message: String = "error.NoElementFoundException",
                                        nestedException: Throwable = null) extends ServiceException
def bla(exception: Throwable) = exception.getMessage
我将这个方法传递给我的
NoElementFoundException
,然后
getMessage
将返回
null

也许我可以通过删除该特性并从
Exception
扩展来轻松解决这个问题:

case class NoElementFoundException(message: String = "error.NoElementFoundException",
                                            nestedException: Throwable = null) extends Exception(message)

但是,有没有办法保持trait?

您需要重写类中的getMessage和getCause方法,以返回属性,而不是从Exception基类返回的属性

case class NoElementFoundException(override val message: String = "error.NoElementFoundException",
                                   override val nestedException: Throwable = null) extends ServiceException {
  override def getMessage: String = message

  override def getCause: Throwable = nestedException
}
我假设(虽然不确定)您并不真的希望您的
ServiceException
s拥有新的公共方法,而不是Exception提供的方法(例如
getMessage
getCause

如果是这种情况,您可以使用
ServiceException
extend
Exception
的扩展器,而无需使用
ServiceException
本身进行扩展:

// "Marker" trait (no methods), extenders must also extend Exception
trait ServiceException { _: Exception => }

// extend Exception with ServiceException
case class NoElementFoundException(message: String = "error.NoElementFoundException",
                                   nestedException: Throwable = null)
      extends Exception(message, nestedException) with ServiceException

// now you can use Exception.getMessage without "duplicating" it into ServiceException:
val exception = NoElementFoundException()
println(exception.getMessage) // prints error.NoElementFoundException

我认为这种特性只会导致混淆,因为
异常
已经有了消息和原因。我会把它换成

trait ServiceException { _: Exception =>
  def message: String = getMessage
  def nestedException: Throwable = getCause
}
或使这些方法能够在所有可丢弃的
上调用

implicit class ThrowableExtensions(self: Exception) {
  def message: String = self.getMessage
  def nestedException: Throwable = self.getCause
}
(在这种情况下,如果您仍然想要
ServiceException
,它将只是一个空的标记特征)