Java ポリモーフィズム(多様性) 〜クラス型の変換と組み合わせ〜

インロトダクション

前回は抽象クラスとインターフェースについて学習しました。

クラスの作り方

クラスの使い方

今回は、以下の3つを組み合わせて、どのような仕組みを作ることができるのか?について学習したいと思います。

はっきり言って、「どのような仕組みを作ることができるのか?」の問いに対する答えは、「ほぼ無限の組み合わせ方、仕組みを作ることができる」と思います。という答えが言えます。

前回までに、クラスとクラスを組み合わせるための土台になる部分を学習しました。以下のような内容です。

  • クラスの継承関係を作成する(親クラスと子クラス)
  • 抽象クラスとインターフェース

これらの仕組み(継承関係を作る)を使用して、どのような組み合わせ方ができるのか学習していきます。
世間巷には「デザインパターン」という名前で広く知られています。が、デザインパターンなどのように広く知られるものは
大体Java APIの方で実装してあるので、使い方さえ分かっていれば改めて実装する必要はありません。

ポイントになるのは、「クラス関係を作成して、どのような仕組みを実現するか?」というところです。

ポリモーフィズムの実装

「テキストRPGを作る」ということをテーマ(話題)として話を進めていきます。

テキストRPG(戦闘シーンのみ)1

テキストRPG(戦闘シーンのみ)2

前回までに作成したもの

まとめると、キャラクターを表現するクラスを作成しました。RpgCharacterクラスを
継承して、必要なパラメータ、HPなどを定義しておき、勇者などのクラスは固有のパラメータのみを保持する形で実装しました。

親クラス、子クラス。。。として以下のようなクラスを作成したいと考えています。下のようなクラスたちです。

具体例A
テキストRPGゲームを作成しようとしているので下のようなクラスを作成したいと思っている。

  1. 勇者・クラス <作成済み>
  2. 魔法使い・クラス <作成済み>
    3.盗賊・クラス
  3. 超勇者クラス
  4. マタンゴ・クラス
  5. ポインズンマタンゴ・クラス
  6. ゴブリン・クラス
  7. ウェアウルフ・クラス
  8. デスバット・クラス

そして、プレーヤー側のクラスの親になるRpgCharacterクラスも作成しました。(詳細は前回を参照ください。)

ポリモーフィズムの設計

先ずは、設計から入ります。

組み合わせて、プログラムを実行するのに「どう組み合わせるか?」を考えないと始まらないのです。

自分の場合は、まずは紙と鉛筆を持ってプログラミングを始めます。つまり「設計から始める」ということです。

RPGのパーティを考える

例えば、前回作成したCharacterクラスとは別に「RpgCharacter」というクラスを作成します。
このクラスは、下の図のように勇者クラス(RpgHero)や魔法使いクラスを作成したとします。

そうすると、下のようなコードが書けます。(エラーが出ません)

<メインメソッド>

    public static void main(String[] args) {
        RpgCharacter[] party = new RpgCharacter[2];
        party[0] = new RpgHero("太郎");
        party[1] = new RpgWizard("二郎");

        System.out.println("こんにちは、良いパーティですね。");
        for (int i = 0; i < party.length; i++) {
            System.out.println(party[i].getName() + "さん");
        }
    }

このように、RpgCharacterクラスを継承しているクラスなので、RpgCharacterの配列をパーティとして扱うことができます。

そして、MonsterもRpgCharacterを継承することになるので、モンスターも仲間(パーティ)に追加できます。

RpgCharacterに処理をまとめる

現状では、勇者や魔法使い、モンスターなどの使用できるコマンドは「たたかう」というコマンドのみです。

ここに、すべてのキャラクターに共通する「にげる」コマンドを追加します。
それには、下のようにコードを追加します。

<RpgCharacterクラスの修正>

public abstract class RpgCharacter {
    /** 名前 */
    protected String name;
    /** HP */
    protected int hp;
    /** MP */
    protected int mp;

    /** にげる */
    public void escape() {
        System.out.println(this.name + "は逃げ出した");
    }
}

この状態で、RpgCharacterクラスを継承するクラスは「にげる」コマンドを使用することができます。

しかし「全く同じではない処理を追加する場合」はどうでしょうか?

例えば、「たたかう」コマンドの場合です。勇者クラスと魔法使いクラスでは、攻撃力が違うはずです。

この場合は、与えるダメージの大きさをそのクラスによって変えられるようにする必要があります。

その仕組みとして「抽象メソッド」を使用する方法があります。

具体的には下のようなコードです。

<抽象メソッドを追加する>

    /** たたかう */
    public abstract void attack(RpgCharacter character);

実装したクラスのコードは下のようになります。

<抽象メソッドを追加したクラス>

public abstract class RpgCharacter {
    /** 名前 */
    protected String name;
    /** HP */
    protected int hp;
    /** MP */
    protected int mp;

    /** たたかう */
    public abstract void attack(RpgCharacter character);
    /** にげる */
    public void escape() {
        System.out.println(this.name + "は逃げ出した");
    }

そして、これらのクラスを生成するとき(newするとき) には、コンストラクタが必要になりますが、これもRpgCharacterクラスと同じものになりますので、下のようにコンストラクタを追加します。

<コンストラクタを追加したクラス>

public abstract class RpgCharacter {
    /** 名前 */
    protected String name;
    /** HP */
    protected int hp;
    /** MP */
    protected int mp;

    /** コンストラクタ */
    public RpgCharacter(String name) {
        this.name = name;
        this.hp = 10;
        this.mp = 0;
    }

    /** たたかう */
    public abstract void attack(RpgCharacter character);
    /** にげる */
    public void escape() {
        System.out.println(this.name + "は逃げ出した");
    }

そうすると初めにも書きましたが、このようなコードでの処理が実行できます。

    public static void main(String[] args) {
        RpgCharacter[] party = new RpgCharacter[2];
        party[0] = new RpgHero("太郎");
        party[1] = new RpgWizard("二郎");

        System.out.println("こんにちは、良いパーティですね。");
        for (int i = 0; i < party.length; i++) {
            System.out.println(party[i].getName() + "さん");
        }
    }

実行結果は下のようになります。

こんにちは、良いパーティですね。
太郎さん
二郎さん

<<<前回 次回 >>>

継承に関するページ一覧

  1. Java オブジェクト指向基礎 ~オブジェクト指向コンセプト~
  2. UMLの書き方(読み方)〜概要とクラス図〜
  3. Java クラスの継承を理解する
  4. クラスの継承〜アクセス修飾子〜
  5. クラスの継承関係を作る1
  6. クラスの継承関係を作る2

環境構築関連ページ一覧

設計関連ページ一覧

  1. 設計を始める〜1.アプリイメージ〜
  2. 設計を始める〜2.機能イメージ〜
  3. 設計を始める〜3.機能概要〜
  4. Java はじめて16 〜クラス設計から実装〜

PHP関連ページ

  1. WordPress プラグイン作成〜DBを使用する〜
  2. PHP PDO 〜MySQLにアクセスする〜
  3. PHP Ajax 〜DBに登録したデータを受信する〜
  4. Google Maps API PHP連携 〜マップ情報をDBに登録する〜
  5. PHP Image File 〜iPhoneやAndroidでの画像送受信の問題〜
  6. AngularJS Routing 〜PHPをWeb APIにする〜
  7. WordPress PHPカスタム〜根本的に見た目を変える〜
  8. WordPress PHPカスタム〜根本的に見た目を変える2〜
  9. Eclipse PHPプラグイン 〜ElipseでWordPress環境を構築〜
  10. WordPress テスト実装 〜heade-test.phpを表示〜
  11. AngularJS + PHP 〜WordPressと連携する〜
  12. AngularJS + PHP 〜AngularJSの実装〜
  13. AngularJS + PHP 〜AngularJSの実装2〜
  14. WordPress 処理解析 ~index.phpを眺める~
  15. WordPress Plugin NewStatPress ~アクセス解析プラグインAPIを使う~
  16. WordPress 処理解析 ~ログイン処理を調べる~
  17. WordPressカスタム〜アンケートボタンを追加する(設計)〜
  18. WordPressカスタム〜プラグインの作成〜
  19. WordPressカスタム〜ダッシュボードのプラグイン画面作成〜
  20. WordPressカスタム〜ダッシュボードのプラグイン画面作成2〜
  21. WordPressカスタム〜ダッシュボードのプラグイン画面作成3〜
  22. WordPress プラグイン作成〜アンケート作成プラグインを作る〜

JS関連ページ

  1. JS GoogleMaps API 〜オリジナル・データマップを作ろう〜
  2. 吹き出しにYoubetubeを埋め込む
  3. Ajax + XmlHttpRequest〜画像送信からDB登録して表示〜
  4. JS XmlHttpRequest 〜JSでの同期/非同期通信〜
  5. JS Google Maps API 〜GeoLocation 現在位置の取得〜
  6. AngularJS + PHP 〜AngularJSの実装〜
  7. AngularJS + PHP 〜AngularJSの実装2〜
  8. WordPress プラグイン作成 〜$wpdbでのSELECT〜
  9. WordPressプラグイン作成 〜HTML挿入まで完了〜
  10. WordPress プラグイン作成 〜アンケート挿入〜
  11. MAMP 起動設定 〜WordPressのテスト環境を作る〜
  12. MAMP WordPress 〜インポート時のエラー対処〜
  13. WordPress PHPカスタム〜根本的に見た目を変える2〜

数理モデル関連ページ

  1. 数学への挑戦 第二弾〜数理モデルxプログラミング〜
  2. 数学への挑戦 第二弾〜実装編:数理モデルxプログラミング〜
  3. 数学への挑戦 第二弾〜集合を使う:数理モデルxプログラミング〜
  4. 数学への挑戦 第二弾〜確率変数:数理モデルxプログラミング〜
  5. 数学への挑戦 第二弾〜期待値と分散:数理モデルxプログラミング〜
  6. 数学への挑戦 第二弾〜卒業までに彼氏ができる確率:数理モデルxプログラミング〜
  7. 数学への挑戦 第二弾〜確率変数の足し算:数理モデルxプログラミング〜
  8. 数学への挑戦 第二弾〜まとめ1:数理モデルxプログラミング〜

投稿者:

takunoji

音響、イベント会場設営業界からIT業界へ転身。現在はJava屋としてサラリーマンをやっている。自称ガテン系プログラマー(笑) Javaプログラミングを布教したい、ラスパイとJavaの相性が良いことに気が付く。 Spring framework, Struts, Seaser, Hibernate, Playframework, JavaEE6, JavaEE7などの現場経験あり。 SQL, VBA, PL/SQL, コマンドプロント, Shellなどもやります。

コメントを残す