Effective Java(第3版)の読書会で出た疑問点について補足します。
共変戻り値型(covariant return type)
共変戻り値型とはJava特有の概念ではなく、オブジェクト指向の一般的な概念です。
クラスを継承してメソッドをオーバライドした場合に、戻り値の型をサブクラスにできる、というものです。
コードで表現すると以下のようになります。
class Parent {
Object create() { return new Object(); }
}
class Sub extends Parent {
@Override
String create() { return "string"; } // オーバライドメソッドの戻り値をサブクラスにできる
}
親クラスの参照を使って子クラスのメソッドを呼んだ場合、戻り値は親クラスの戻り値の型で受けることになりますが、
実体がサブクラスであっても代入可能なので問題ありません。
この性質はJava5でジェネリクスに合わせて導入されました。
(ジェネリクスの型の処理はこの性質を使っているため)
この変更により、呼び出し元でのキャストが不要になっています。
不変式
プログラミングにおいて不変式、不変条件という場合、常に真になる条件のことです。
例として、期間を表すクラスにおいて 開始時刻 <= 終了時刻 の様に、
常に真になる(仮にこのクラスのフィールドが変更可能でも、偽になる瞬間が
無い)
条件を表します。
Builderパターンを使用することで、オブジェクトが不変式を満たすことを容易に保証することができます。
コード例中のselfメソッドのアクセス修飾子
かなり細かい点ですが、P14の
protected abstract T self();
という記載について、なぜprotectedなのか、という疑問が出ました。
実際にコードを動かして確認しましたが、パッケージプライベートで問題ありません。
selfメソッドが定義されているBuilderクラスがパッケージプライベートですので、
パッケージ外で継承することを意図していませんし、
メソッドもクラスと同じくパッケージプライベートで十分です。
「項目15 クラスとメンバーへのアクセス可能性を最小限にする」に反していますので
著者のミスかもしれません。