ポリモーフィズムの入口を理解する
多態性は共通の親クラスやインタフェースの型を通じて、実体ごとに異なる処理を呼ぶ仕組みです。宣言型で使える操作を検査し、実体型でオーバーライド先を選び、必要な参照型キャストを安全に判断します。
この単元で学ぶこと
- 共通型を通じた動的呼出しを追う
- 拡大参照変換とキャストの成功条件を判定する
- instanceofとnullを使った型検査を判断する
本文解説
共通の操作を呼ぶ abstract class Shape{abstract int area();}をSquareとTriangleが実装すると、Shape[]に両実体を入れてarea()を順に呼べます。呼出し側は具体クラスごとの名前で分岐せず、共通の契約を使います。これが多態性の基本です。
抽象型の変数 Shape s=new Square()は合法です。禁止されるのはnew Shape()という抽象クラスの直接生成であり、抽象型の変数宣言ではありません。インタフェース型も同様に、実装クラスの参照を保持できます。
宣言型で操作を検査 Shapeにareaだけがあれば、Squareだけのside()をs.side()で直接呼べません。実体がSquareでもコンパイル時にはShapeの契約を基準に検査します。必要なら契約に操作を設計するか、型を確認して明示的にキャストします。
拡大参照変換 Child c=new Child();Parent p=c;は同じ実体を親として扱います。コピーして別の親オブジェクトを作る操作ではないため、p==cはtrueです。共通型にしても実体の型と子のオーバーライドは保たれます。
親から子へのキャスト Parent p=new Child();Child c=(Child)p;は実体がChildなので成功します。Parent p=new Parent();Child c=(Child)p;はコンパイルできても実行時にClassCastExceptionです。キャストによってParent実体へ子のフィールドを付け足すわけではありません。
instanceofで検査 p instanceof Childはpが非nullでChildまたはその子として扱える実体ならtrueです。pがParentだけの実体ならfalseです。if(p instanceof Child){Child c=(Child)p;...}なら、このブロック内のキャストを実体に照らして行えます。Java 11なのでパターン変数構文は使いません。
nullの型操作 Parent p=null;Child c=(Child)p;は成功しcもnullです。p instanceof Childはfalseです。キャスト成功後にcのインスタンスメソッドを呼ぶとNullPointerExceptionなので、キャストが通ることと非nullであることは別です。
契約を実装する複数のクラス interface Named{String name();}に対してUserとTeamが実装すれば、Named nを介してそれぞれのnameを呼べます。同じ操作を持つことを明示的なimplementsで結びます。型変換はこの宣言上の関係と実体の両方に従います。
図解
重要ポイント
- 宣言型は呼出せるメンバー、実体型はオーバーライドの実行先に関係する。
- 子から親・実装クラスからインタフェースへの代入は可能。
- 親から子へ戻すキャストは実体がその型である必要がある。
- キャストは実体を作り替えず、nullのinstanceofはfalse。
間違えやすい点
- キャストすればどんな親実体も子へ変わると思わない。
- instanceofがクラス名の完全一致だけを調べると思わない。
- interfaceやabstract型の変数を宣言できないと思わない。
用語解説
- 多態性
- 共通型の操作を実体に応じた実装で実行すること。
- 拡大参照変換
- 子から親等、より一般的な型として扱う変換。
- キャスト
- 明示的に型を指定して式を扱う変換。参照変換には実行時検査がある。
- instanceof
- 非nullの参照が指定型として扱える実体かを検査する演算子。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
- https://www.oracle.com/jp/education/certification/certification-exam-list/java-se-bronze-1z0-818-exam/
- https://docs.oracle.com/javase/specs/jls/se11/html/jls-8.html
- https://docs.oracle.com/javase/specs/jls/se11/html/jls-5.html
- https://docs.oracle.com/javase/specs/jls/se11/html/jls-6.html
- https://docs.oracle.com/javase/specs/jls/se11/html/jls-7.html
- https://docs.oracle.com/javase/specs/jls/se11/html/jls-9.html
- https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html
確認問題の出題・採点や学習履歴の保存にはログインが必要です。