1
メソッドのオーバーライド
スーパークラスのメソッドを、サブクラスで同じ形のまま上書きすることをオーバーライドといいます。
OverrideSample.java
class Rectangle {
void setSize(int width, int height) {
System.out.println("Rectangle");
}
}
class NamedRectangle extends Rectangle {
@Override
void setSize(int width, int height) {
System.out.println("NamedRectangle");
}
}- メソッド名親と同じ名前にする。
- 引数型、個数、並びを同じにする。
- 戻り値互換性のある戻り値型にする。
@Override を付けると、正しく上書きできているかコンパイラが確認します。
オーバーロードとの違い
| 種類 | 定義 | 例 |
|---|---|---|
| オーバーライド | 継承先で同じシグネチャのメソッドを上書き | 親と子の play() |
| オーバーロード | 同名で引数が異なるメソッドを複数定義 | abs(int)、abs(double) |
2
多態性
多態性とは、同じメソッド呼び出しでも、実際のインスタンスによって異なる処理が実行される仕組みです。
変数の型
→
Player実際のインスタンス
→
new MusicPlayer()実行する処理
MusicPlayer.play()多態性の基本
Player player = new MusicPlayer();
player.play(); // MusicPlayer側のplay()を実行変数の型が Player でも、実体が MusicPlayer なら、Javaは実行時に実体へ対応するメソッドを選びます。
3
フィールドの隠蔽とfinal
子クラスで親クラスと同名のフィールドを宣言すると、子クラス側のフィールドが通常見える状態になります。これはメソッドのオーバーライドとは別の仕組みです。
フィールドの隠蔽
class A {
int x = 1;
}
class B extends A {
int x = 5;
}| 宣言 | 制限 | 用途 |
|---|---|---|
final void execute() | 子クラスでオーバーライドできない | 変更させたくない重要な処理 |
final class Sample | そのクラスを継承できない | 継承を前提としない設計 |
String、Integer、System、Math は代表的なfinalクラスです。
4
パッケージとアクセス修飾子
パッケージは関連するクラスをまとめる単位です。java.lang は自動的に利用できますが、それ以外は通常 import します。
importの例
import java.io.BufferedReader;
import java.io.*;| 修飾子 | 同じクラス | 同じパッケージ | サブクラス | その他 |
|---|---|---|---|---|
private | ○ | × | × | × |
| 修飾子なし | ○ | ○ | 同じパッケージなら○ | × |
protected | ○ | ○ | ○ | × |
public | ○ | ○ | ○ | ○ |
5
情報隠蔽とアクセサ
親クラスの private メンバーは、子クラスからも直接アクセスできません。値は公開されたメソッドを通して扱います。
安全にフィールドを管理する
class Rectangle {
private int width;
public int getWidth() {
return width;
}
public void setWidth(int width) {
if (width >= 0) {
this.width = width;
}
}
}- getterフィールドの値を取得する。
- setterフィールドへ値を設定する。
- 検証不正な値を代入する前にチェックできる。
6
抽象クラスと抽象メソッド
抽象クラスは、共通のフィールドや処理を持ちながら、具体的な処理の一部を子クラスに任せるクラスです。
抽象クラスの基本
abstract class Player {
abstract void play();
}
class MusicPlayer extends Player {
@Override
void play() {
System.out.println("音楽を再生します");
}
}抽象クラスは直接インスタンス化できません。new Player() はコンパイルエラーです。
抽象クラスを継承した通常のクラスは、抽象メソッドを実装する必要があります。
7
そのまま動く多態性サンプル
次のコードを PolymorphismSample.java として保存すると、抽象クラス、オーバーライド、多態性をまとめて実行できます。
PolymorphismSample.java
abstract class Player {
private String name;
Player(String name) {
this.name = name;
}
String getName() {
return name;
}
abstract void play();
}
class MusicPlayer extends Player {
MusicPlayer(String name) {
super(name);
}
@Override
void play() {
System.out.println(getName() + ": 音楽を再生します");
}
}
class MoviePlayer extends Player {
MoviePlayer(String name) {
super(name);
}
@Override
void play() {
System.out.println(getName() + ": 動画を再生します");
}
}
class GamePlayer extends Player {
GamePlayer(String name) {
super(name);
}
@Override
void play() {
System.out.println(getName() + ": ゲームを開始します");
}
}
public class PolymorphismSample {
public static void main(String[] args) {
Player player1 = new MusicPlayer("音楽プレイヤー");
Player player2 = new MoviePlayer("動画プレイヤー");
Player player3 = new GamePlayer("ゲームプレイヤー");
player1.play();
player2.play();
player3.play();
}
}コンパイルと実行
javac PolymorphismSample.java
java PolymorphismSample実行結果を確認する
output
音楽プレイヤー: 音楽を再生します
動画プレイヤー: 動画を再生します
ゲームプレイヤー: ゲームを開始します8
確認問題
- オーバーライドの間違いをコンパイラに確認させる注釈は何ですか。
- 親クラスのprivateフィールドを子クラスから安全に取得するには何を使いますか。
- Player player = new MusicPlayer(); の player.play() では、どのクラスの処理が実行されますか。
解答を確認する
- @Override です。
- 親クラスが公開するgetterなどのメソッドを使います。
- 実体に対応する MusicPlayer の play() が実行されます。