Javaデモ/単純化している「CUI対戦デモ」 オブジェクト指向プログラミング

 このデモの多態性(ポリモーフィズム)は あくまでも形式的な多態性(ポリモーフィズム)なので、多態性(ポリモーフィズム)に関しては別途 勉強が必要です。

下記『Javaデモ/Swingグラフィック「Thread、Figure」(2)』は「抽象化(アブストラクション)、継承(インヘリタンス)、多態性(ポリモーフィズム)、合成(コンポジション)」を具現化していますが、多態性(ポリモーフィズム)の教材としても最適です。

なお、このデモでは「合成(コンポジション)、集約(アグリゲーション)」が曖昧になっています。


Javaデモ/Swingグラフィック「Figure、Thread」(2) オブジェクト指向プログラミング

https://sphinx1335.blogspot.com/2026/03/javaswingfigurethread2.html


もっとガッツリやりたい場合は下記で勉強すると良いでしょう。


Javaデモ/CUI対戦デモ(10) オブジェクト指向プログラミング

https://sphinx1335.blogspot.com/2026/03/javacui10.html


集約とコンポジションの例えについて

https://qiita.com/gatapon/items/5e3292f897ab4f817001


>コンポジション

>保持されているものが保持しているものの一部である場合

>この書籍では「車とエンジン」で例えられています。


>集約

>独立して存在できる何かのコレクションがある場合

>こちらは空港と飛行機で例えられています。


その他の要件としては親オブジェクトが消滅する時に、確実に子オブジェクトも消滅するなら合成(コンポジション)と考えて良いです。



CUI(character user interface)の対戦デモです、そして「抽象化(アブストラクション)、継承(インヘリタンス)、合成(コンポジション)」のデモでもあります。

あくまでもデモなので、手抜きをしています、「getter、setter」メソッドを どうするとか、「治癒、防御」を どうするかとか。


「継承(インヘリタンス)」で対応できない場合に「集約(アグリゲーション)、合成(コンポジション)、委譲(デリゲーション)」などを使います、オブジェクト内に機能拡張用オブジェクトを作ることを「集約(アグリゲーション)、合成(コンポジション)」と言い、自オブジェクト・メソッド内で「集約(アグリゲーション)、合成(コンポジション)」オブジェクト・メソッドを呼び出している場合は委譲(デリゲーション)と言います。


「ArrayList<CharEssence> d1oMember」が合成(コンポジション)になりますが、概念的にはPartyを解消してもキャラは独立して存在しても良いので集約(アグリゲーション)とも考えられます。


オブジェクト指向プログラミングの1番の肝は多態性(ポリモーフィズム)であり、その多態性(ポリモーフィズム)の肝は「共通の機能」(メソッド)を抽出することです(2番目の肝は「集約(アグリゲーション)、合成(コンポジション)」です)。

ちなみに肝となる「共通の機能」が複数 存在する場合もあります。

この場合、「CharEssence」クラスでは「Influence()、Passive()」が肝となる「共通の機能」となりますが、その肝となる「共通の機能」が抽出できるか どうかがオブジェクト指向プログラミングができるか どうかの基準になります。

肝となる「共通の機能」(メソッド)は、その機能ごとに完全にシグネチャが一致していなければなしません(コンストラクタや その他のメソッドは必ずしもシグネチャが一致しなくても良いです)。



勉強のために「スライム(Slime)、ゴブリン(Goblin)」などを追加してみると良いでしょう。

「スライム(Slime)、ゴブリン(Goblin)」クラスなどを追加したい場合は、「怪物(Monster)」クラスの子クラスに定義すれば良いでしょう。


「CharEssence」クラスの継承関係は下記のとおりです。


─CharEssence

␣├人間(Human)

␣│├勇者(Hero)

␣│├戦士(Fighter)

␣│└魔法使い(Magician)

␣└怪物(Monster)

␣␣└竜(Dragon)



import java.util.ArrayList;

import java.util.Random;


public class J191 {

  public static void main(String[] args) {

    Party enemyParty = new Party();

    enemyParty.add(new Dragon("ドラゴン"));

    enemyParty.add(new Fighter("シロ"));

    enemyParty.add(new Magician("クロ"));

    System.out.println("enemyParty");

    System.out.println(enemyParty);

    System.out.println();


    Party myParty = new Party();

    myParty.add(new Hero("アカ"));

    myParty.add(new Fighter("ミドリ"));

    myParty.add(new Magician("アオ"));

    System.out.println("myParty");

    System.out.println(myParty);

    System.out.println();


    do {

      myParty.PartyInfluence(enemyParty);

      System.out.println("enemyParty");

      if (enemyParty.size() <= 0) {

        System.out.println("全滅");

        break;

      }

      System.out.println(enemyParty);

      System.out.println();


      enemyParty.PartyInfluence(myParty);

      System.out.println("myParty");

      if (myParty.size() <= 0) {

        System.out.println("全滅");

        break;

      }

      System.out.println(myParty);

      System.out.println();

    } while (0 < myParty.size() & 0 < enemyParty.size());

  }

}


class Party {

  ArrayList<CharEssence> d1oMember = new ArrayList<CharEssence>();


  public int size() {

    return d1oMember.size();

  }


  public CharEssence get(int index) {

    return d1oMember.get(index);

  }


  public void add(CharEssence one) {

    d1oMember.add(one);

  }


  public void remove(int index) {

    d1oMember.remove(index);

  }


  public void PartyInfluence(Party oppoParty) {

    for (int i = 0; i < size(); i++) {

      for (int j = oppoParty.size() - 1; 0 <= j; j--) {

        oppoParty.get(j).Passive(get(i));

        if (oppoParty.get(j).getHP() <= 0) {

          oppoParty.remove(j);

        }

      }

    }

  }


  @Override

  public String toString() {

    String[] j = new String[d1oMember.size()];

    for (int i = 0; i < d1oMember.size(); i++) {

      CharEssence one = d1oMember.get(i);

      j[i] = String.format("%s:%s HP:%.1f", //

          one.getCategory(), one.getName(), one.getHP());

    }

    return String.join("; ", j);

  }

}


abstract class CharEssence {

  double fHP;

  int iPower;

  String sName;

  static Random random = new Random();


  public CharEssence(String name) {

    sName = name;

  }


  public String getCategory() {

    return getClass().getSimpleName();

  }


  public double getHP() {

    return fHP;

  }


  public String getName() {

    return sName;

  }


  public double Influence() {

    return iPower * random.nextDouble();

  }


  public void Passive(CharEssence oppoChar) {

    double impact;

    if (0 < getHP() & 0 < oppoChar.getHP()) {

      impact = oppoChar.Influence();

      fHP = Math.max(0, fHP - impact);

    }

  }

}


abstract class Human extends CharEssence {

  public Human(String name) {

    super(name);

  }

}


class Hero extends Human {

  public Hero(String name) {

    super(name);

    fHP = 300;

    iPower = 30;

  }

}


class Fighter extends Human {

  public Fighter(String name) {

    super(name);

    fHP = 200;

    iPower = 20;

  }

}


class Magician extends Human {

  public Magician(String name) {

    super(name);

    fHP = 100;

    iPower = 10;

  }

}


abstract class Monster extends CharEssence {

  public Monster(String name) {

    super(name);

  }

}


class Dragon extends Human {

  public Dragon(String name) {

    super(name);

    fHP = 300;

    iPower = 30;

  }

}

コメント

このブログの人気の投稿