共変返却型メカニズムは、Javaにおいてメソッドをオーバーライドする際に、スーパークラスとまったく同じ型ではなく、そのサブタイプを返すことを可能にします(共変型)。
これにより、明示的なキャストなしでより具体的な型を取得できるようになり、コードの表現力が向上します。
例:
class Animal { } class Dog extends Animal { } class Parent { Animal getAnimal() { return new Animal(); } } class Child extends Parent { @Override Dog getAnimal() { return new Dog(); } // 共変返却 }
動作条件:
サブクラスでオーバーロードメソッドの戻り値の型をベースのサブタイプに変更することはできますか?それは有効なオーバーロードと見なされますか?
回答: いいえ、オーバーロードの場合、重要なのはパラメーターのシグネチャのみであり、戻り値の型は関係ありません。戻り値の型だけをオーバーロードで変更することはできません—そのようなメソッドはシグネチャが衝突します。
例:
class Example { Animal make() { return new Animal(); } // Dog make() { return new Dog(); } // コンパイルエラー: 重複メソッド! }
共変性はオーバーライディング(オーバーライド)のみで機能します。
歴史
プロジェクトでプログラマが間違って、同じ名前とパラメーターを持つオーバーロードメソッドを異なる戻り値の型で追加し、これを「共変オーバーライド」と期待した結果、プロジェクトがコンパイルされず、CIの際にバグが発見されました。
歴史
クラスの階層で共変返却を使用する際に、開発者がパラメータ化された型(ジェネリクス)を不正に適用し、サブタイプを正しく実装しなかったため、コレクションを操作する際にClassCastExceptionが発生しました。
歴史
オーバーライドされるメソッドがより専門的な型を返していましたが、チームはこの契約を文書化しませんでした。ベース型を介して動作するコードでは、型キャストに関する困難や、リンクの「アップキャスト」での予期しない動作が発生し、複数の隠れたバグが生じました。