Javaのsealedクラス、公開APIで使うと実行時に壊れる罠
Java sealed classes and exhaustive pattern matching
Java 17のsealedクラスは全ケース網羅をコンパイラが保証してくれるが、それは利用側を再コンパイルした場合に限られる。公開APIにsealed型を露出させると、サブタイプ追加のたびに利用側が壊れ、しかも再コンパイルされなければMatchExceptionが実行時に飛ぶ。著者はPEM暗号オブジェクトのプレビューAPIがまさにこの過ちを犯していると指摘する。
sealed型はコンポーネントの実装内部でこそ最も有用で、ライブラリのように外部へ公開するAPIでは有用性が低い。
HNでの議論
106- shepherdjerred
Javaがここまで進化したのは本当に素晴らしい。フロントエンドの仕事が多いので、スタック全体で同じ言語を使いたいから、自分は今でもTypeScriptの方が好きだけどね。
そうは言っても、TypeScriptでも網羅的なパターンマッチングができるんだ!https://github.com/gvergnaud/ts-pattern
- armchairhacker
Javaには再帰パターンと、(まだプレビューかもしれないが)リテラルパターンもある:`switch (x) { case A(B(true, var c)) -> f(c); }`
- another_twist
sealedに慣れるまで時間がかかったし、使い道がよくわからなかった。でもAIがJavaでsealedをやたら好むみたいなので試してみたら、今は理解できた。特にDIを使っていて非推奨にしたいものがある場合、これは本当に優れたアクセス制御の仕組みだと思う。もちろんパターンマッチングは、ペイロードの形が変わるイベント駆動メッセージで重宝するけどね。
- timshel2
Scalaが今ごろ悔しがってるよ
- panny
sealed型を使うなら、そういうswitchのdefaultは必要ないと思う。コンパイラで確認したわけじゃないけど、不要だと思うよ。
- Larrikin
JavaはKotlinに追いつこうとし続けている
https://kotlinlang.org/docs/sealed-classes.html
比較対象がC++やRuby、Pythonだった頃はJavaも悪くないと思ってた。でもScala(無差別すぎて失敗したように見えた)を経て、特にKotlinの後では、戻る理由が見つからない。