このStackOverflowの質問 で、Scalaの@throws
アノテーションの動作について質問しました。それがどのように機能するかを理解したので、それを使用する際のベストプラクティスについて尋ねたいと思います。これがその質問からの私のコードの再投稿です:
abstract class SFoo {
def bar(): Unit
}
class SFoobar extends SFoo {
@throws[Exception]
override def bar(): Unit = {
throw new Exception("hi there")
}
}
ここでの問題は、Javaで変数をSFoo
として宣言し、SFoobar
としてインスタンス化すると、Javaコンパイラーがチェック例外と実行時例外が発生するので、親クラスSFoo
で@throws
を宣言する傾向があります。
しかし、SFoo
の別の具体的な実装があるとしましょう。
class SBarfoo extends SFoo {
override def bar(): Unit = {
println("no exception here!")
}
}
この場合、その実装の1つが例外をスローしない場合、親クラスで@throws
を宣言することは適切ですか?ここでのベストプラクティスは何ですか? (主観的な質問で申し訳ありません。)
@throws
コントラクトが満たされるために、毎回例外をスローする必要はありません。実際、ほとんどの場合、そうはしません。それが本当にサブクラスとして属している場合、例外をスローしない実装があることには何の問題もありません。それが理にかなっている多くのアプリケーションを考えることができます。たとえば、ある実装ではディスクキャッシュを使用し、別の実装ではメモリキャッシュを使用する場合があります。
そうは言っても、Scalaは、正当な理由で意図的にチェックされた例外を省略しました。それらは、オープン/クローズの原則に違反しています。階層、およびそれらのメソッドを呼び出すメソッド。問題のあるチェック例外が実際のJavaアプリケーションに存在することが判明したため、チェック例外はC#およびその他の最近の言語からはほとんど除外されました。 Scalaは、Javaコードとの互換性について例外のみをチェックしました。 ScalaコードからJavaコードを呼び出さない場合は、使用しないでください。