例外をcase classとして定義してはいけない

Scalaで独自の例外を定義する場合

class MyException(message: String) extends RuntimeException(message)

case class MyException(message: String) extends RuntimeException(message)

のどちらが良いでしょうか。タイトルで言っちゃってますが、まずほとんどの場合はcase classではなくclassを使う方が良いと思います。

case classにすると等価性がそのインスタンスの属性によって判断されるので、同じ属性を持っている例外は同じものと見なされます。

scala> case class MyException(message: String) extends RuntimeException(message)
defined class MyException

scala> MyException("error")
res0: MyException = MyException: error

scala> MyException("error")
res1: MyException = MyException: error

scala> res0 == res1
res2: Boolean = true

一方、classの場合はequalsをオーバーライドしていない限り、属性が同じでもインスタンスが別なら別物です。

scala> class MyException(message: String) extends RuntimeException(message)
defined class MyException

scala> new MyException("error")
res0: MyException = MyException: error

scala> new MyException("error")
res1: MyException = MyException: error

scala> res0 == res1
res2: Boolean = false

基本的にはcase classではなくclassを使った時の挙動が好ましいと思います。messageが同じとはいえ、起きたタイミングの異なる2つの例外を同じものと見なすのは不自然ではないでしょうか。スタックトレースだって異なるかもしれないですしね。