クラスの継承とインターフェースの実装における違いを考えたのでまとめます。
また、私が大好きなドラクエに例えて実装したいと思います。
この記事の対象読者
- オブジェクト指向の基本的な用語がなんとなくわかる人
- ドラクエをやったことがある人(推奨)
この記事でわかること
- クラスの継承とインターフェース実装における違い
- インターフェースを利用するメリット
クラスの継承
- 親クラスの
state
(状態)やmethod
(挙動)を子クラスで利用できるようになる - 子クラスのみの
state
やmethod
を定義することができる - オーバーライドすることで親クラスの
method
を上書きできるようになる - ただし、継承できるクラスは1つまで
インターフェースの実装
- インターフェースはオブジェクトが実装しなければならない
method
(挙動)を定義する - インターフェースは
抽象メソッド
のみ定義することができる -
抽象メソッド
は実装した先のオブジェクトで記述しなければエラーが発生する、そのため抽象メソッドの実装を強制させることができる - インターフェースはクラスと違い、複数実装できる
ドラクエで例えてみる
私が大好きなゲームのドラクエで例えたいと思います。
今回はスライムとメタルスライム、はぐれメタルを実装します。
スライム
- ドラクエの顔とも言える人気モンスター
- レベル1の主人公でも倒せる一番弱いモンスター
メタルスライム
- メタル系モンスター
- 倒すとたくさん経験値が貰えるためレベルアップしやすい
- 今回は炎系の呪文のメラを唱える
- すぐ逃げる
はぐれメタル
- メタル系モンスター
- 倒すとたくさん経験値が貰えるためレベルアップしやすい。
- 今回は炎系の呪文のベギラマを唱える。
- すぐ逃げる
それでは実装してみます。
モンスター(クラス)
まずは親クラスである「モンスタークラス」を定義します。
全てのモンスターはこのクラスを継承します。
class Monster {
public String name;
public int hp;
public int attackPower;
public Monster(String name, int hp, int attackPower) {
this.name = name;
this.hp = hp;
this.attackPower = attackPower;
}
public void attack() {
System.out.println(this.name + " の攻撃!");
}
}
スライム(クラス)
「モンスタークラス」を継承した「スライムクラス」です。
「attackメソッド」をオーバーライドし、メッセージの出力を「体当たり」に変更しています。
class Slime extends Monster {
public Slime(String name, int hp, int attackPower) {
super(name, hp, attackPower);
}
// オーバーライド
public void attack() {
System.out.println(this.name + "の体当たり!");
}
}
メタルタイプ(インターフェース)
メタル系モンスターの実装のため、「メタルタイプインターフェース」を定義します。
メタル系モンスターの特徴として「runAway(逃げる)」を抽象メソッド
として定義します。
interface MetalType {
abstract public void runAway();
}
メタルスライム(クラス)
「メタルスライムクラス」は「モンスタークラス」を継承し、「メタルタイプインターフェース」を実装します。
「メタルスライムクラス」独自のメソッドとして「magicメソッド」を定義します。
「メタルタイプインターフェース」を定義した「runAwayメソッド」を実装します。
class MetalSlime extends Monster implements MetalType {
public MetalSlime(String name, int hp, int attackPower) {
super(name, hp, attackPower);
}
// オーバーライド
public void attack() {
System.out.println(this.name + "の体当たり!");
}
// MetalSlimeクラス独自のメソッド
public void magic() {
System.out.println(this.name + "はメラを唱えた!");
}
// 実装しなければエラー
public void runAway() {
System.out.println(this.name + "は逃げ出した");
}
}
はぐれメタル(クラス)
「はぐれメタルクラス」は「モンスタークラス」を継承し、「メタルタイプインターフェース」を実装します。
「はぐれメタルクラス」独自のメソッドとして「magicメソッド」を定義します。
class HagureMetal extends Monster implements MetalType {
public HagureMetal(String name, int hp, int attackPower) {
super(name, hp, attackPower);
}
// オーバーライド
public void attack() {
System.out.println(this.name + "の体当たり!");
}
// HagureMetalクラス独自のメソッド
public void magic() {
System.out.println(this.name + "はベギラマを唱えた!");
}
}
上記のコードでは「メタルタイプインターフェース」で定義した抽象メソッド
の「runAway(逃げる)」を実装していません。そのためVSCodeではエラーが以下のように表示されます。
抽象メソッド
であるrunAwayを実装しなさいと怒られていますね。
インターフェースのメリット
インターフェースで定義した抽象メソッドを実装し忘れるとエラーが表示されます。
これがインターフェースを利用するメリットですね。
メタルスライムは「逃げる」、はぐれメタルは「逃げない」状態でゲームがリリースされると、はぐれメタルが倒し放題でレベルアップが簡単になり、ゲームバランスが崩壊します(笑)。
インターフェースを定義すると実装漏れを防ぐことができるので非常に便利ですね。
最後に
ドラクエに例えて考えることでオブジェクト指向の理解が少し深まった気がします。
今後もオブジェクト指向の記事を何かに例えて書いていきたいと思います!
最後に今回のクラス図を記載して終わります!
参考
コンピュータサイエンスが学習できるプラットフォーム「Recursion」のOOPコースで学んだことを参考に記事にしました。
連結リストやスタックなどのデータ構造、デザインパターンについて学べるのでオススメです。