第二十章 
 〜クラス編〜
 ポリモーフィズム
 ここ最近やって来たオーバーライド、抽象クラスとどれも継承を利用していたですね
そして今回出てくるポリモーフィズムと言う機能は、これらの応用です。逆に言うとこ
れらを分かっていればすぐに分かると思うです〜。
 ポリモーフィズムと言うのは、同じメソッド名で違う処理をすると言う機能です。
これは実際にサンプルを打ってもらってから説明した方が分かりやすいので先にサンプ
ルを見てほしいです。
サンプルはRei19_1の少し改良したやつです〜。
Animalクラス、Carnivorousクラス、Herbivorousクラスは
Rei19のサンプルと全て同じです。
Rei20_1
 1:
 2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
 34:
 35:
 36:
 37:
 38:
 39:
 40:
 41:
 42:
 43:
 44:
 45:
 46:
 47:
 48:
 49:
 50:
 51:
class Rei20_1{
    public static void main(String[] args){
        Animal[] animals = {new Carnivorous(), new Herbivorous()};

        for(int i=0; i<animals.length; i++){
            animals[i].eat();
        }
    
        for(int i=0; i<animals.length; i++){
            String element = animals[i].getType();
            int ryou = animals[i].getRyou();

            System.out.println(element + "が食べた量" + ryou);
        }
    }
}

abstract class Animal{
    protected int ryou;

    public int getRyou(){
        return ryou;
    }

    public abstract void eat();
    public abstract String getType();
}

//肉食動物////////////////////////
class Carnivorous extends Animal{
    public void eat(){
        System.out.println("肉を食べる");
        ryou = 1000;
    }

    public String getType(){
        return "肉食動物";
    }
}

//草食動物////////////////////////
class Herbivorous extends Animal{
    public void eat(){
        System.out.println("草を食べる");
        ryou = 300;
    }

    public String getType(){
        return "草食動物";
    }
}

 今回のプログラムで久々に配列が登場しているですね!
その配列についてまず説明するです。
Animal型のanimalsの配列にそれぞれ、CarnivorousクラスHerbivorousクラスオブ
ジェクト
を作成しているです。実はこの1行は分解することができるです。これは配列
のときにやったですね!つまり次のようになるです〜
Animal[] animals = new Animal[2];
animals[0] = new Carnivorous();
animals[1] = new Herbivorous();
 分解してみると、animalsの配列の0番目、1番目にそれぞれのオブジェクトが作成さ
れることが分かるですね!でも今回は配列以外にもう1つ今までとは違うことがあるです
それは、オブジェクトを作成するときの宣言の仕方です。
 今までだとクラス名 オブジェクト名 = new クラス名のコンストラクタ名();で
クラス名とコンストラクタ名は同じだったです。
例:Carnivorous tora = new Carnivorous();
しかし今回は同じじゃないです。ちょっと配列になっているので分かりにくいですが、
次のように書いてみるです。
Animal tora = new Carnivorous();
これを説明すると次のようになるです。アニマルのトラを肉食動物で作成する。
アニマルのトラは肉食動物だと、とらえてくれればいいです。こう考えてみると
今説明したアニマルのトラは肉食動物だは間違ってないですね!だから
Animal tora = new Carnivorous();と書くことができるです。
 でも実は説明が矛盾しないから書けるというものではないです。実はCarnivorousク
ラスがAnimalクラスを継承しているから書くことができるのです。つまり今言った事を
踏まえて書式に表すと次のようになるです〜
 スーパークラス名 オブジェクト名 = new サブクラスのコンストラクタ名();
説明が長くなってしまったですが今言った1行を書くことができると思ってくれればい
いです。1つ注意が必要なのが、スーパークラス名で定義したオブジェクトはサブクラ
スで新たに定義したメソッドやフィールドは扱うことはできないです。

 実はまだポリモーフィズムの説明には入ってないです・・・

 5行目や9行目に、書いてあるanimals.lengthは、配列の長さを取得しているですね!
つまりここだとanimalsのオブジェクトは合計2個なので2が取得されるです。

 いよいよ本題のポリモーフィズムの説明に入っていくです。そのポリモーフィズムを
行っているのはanimals[i].eat();animals[i].getType();の2つです。これらをそれ
ぞれ実行した場合、animals[i].eat();だとまずiの値が0のときCarnivorousクラス
eat()メソッドが呼ばれるです。そしてiの値が1のときにはHerbivorousクラスeat()
メソッド
が呼ばれるです。getType()のときも同じです。このように宣言したときのオ
ブジェクトによって、同じメソッド名でも違う処理をすることをポリモーフィズムと
呼んでいるです。
 ちなみに、なぜそれぞれに合ったメソッドが呼ばれるのかは、オーバーライドのとこ
ろでやったですね!それは、スーパークラスのメソッドをサブクラスで再定義している
からだったですね。再定義をするメソッドの元となるメソッド(スーパークラスにある
メソッド)を絶対に抽象メソッドにしなければいけないと言う決まりはないです。
 この章の一番最初にも言ったですが、ポリモーフィズムを理解するには、継承やオー
バーライド、抽象クラスなどを理解していないと難しい機能です〜。でもこのポリモー
フィズムは使えるようになるとかなり便利になるので、ぜひ覚えてほしいです〜。
(覚えて欲しくない機能は一つもないです。)

 ポリモーフィズムの説明は終わったですが、わざわざスーパークラスの方に処理が無
い抽象メソッドを書く必要があるのか説明しておくです。
 普通に考えれば、あとからそれぞれのサブクラスで宣言しているので書く必要は無い
と思うかもしれないです。animals.lengthの前当たりで説明したですが、スーパークラ
ス名で定義したオブジェクトはサブクラスで新たに定義したメソッドやフィールドは扱
うことはできないです。と書いたはずです。
 この説明にもあるようにサブクラスで定義したものは利用できないのです。つまりポ
リモーフィズムを利用したい場合は、必ずスーパークラスで宣言をしてそれをオーバー
ライドしてあげないといけないのですね!そして書く必要も無かった処理なので抽象メ
ソッドを宣言しているです。(抽象クラスの説明でやったときとちょっと違うですが、
こう覚えた方が覚えやすいかなと思って書いてみたです。)


今回のポイント
@ 同じメソッドでも宣言したときのオブジェクトによって違う処理をすることを
  ポリモーフィズムと言う
A スーパークラス名 オブジェクト名 = new サブクラスのコンストラクタ名();
  と書くことができる。
B サブクラスで新たに定義したフィールドやメソッドはスーパークラスで宣言した
  オブジェクトからは利用できない。
  例を出していなかったので例を出すです〜
      class Rei{
          public static void main(String args){
              A a1 = new B();
              A.b=100;   //この処理はできないです
          }
      }
      class A{
          int a;
      }
      
      class B extends A{
          int b;
      }

TOPに戻る   Java講座に戻る