多態性(ポリモーフィズム)

  1. 多態性
    1. 多態性(ポリモーフィズム)
      同じスーパークラスMを継承した二つのサブクラスのインスタンスp1、t1が同じ名前のメソッドplay()を定義しているとき、mをMのインスタンスとして
       m=p1;m.play();
       m=t1;m.paly();
      で、同じ m.paly() で異なる処理をすることができます。上はp1のplay下はt1のplay()をします。これを多態性と呼んでいます。
       ここで、m=p1 への代入ができることに注意してください。Javaでは、原則的に異なるクラス間の代入はできません。しかし、サブクラスの値をスーパー(親)クラスの変数に代入することは許されています。これが、多態性を可能にするトリックです。

    2.  
      具体的に例を挙げます。musicianのplay()はPianistとTrumpeterのクラスのplay()でオーバ−ライドされます。
      class musician{
       void play(){System.out.println("play music");};
      }
        
      class Pianist extends musician{
       public void play(){ System.out.println("play piano");}
        }
        
      class Trumpeter extends musician{
       public void play(){ System.out.println("play trumpet");}
       }
      
      class Concert{
       Concert(){
        Pianist p1=new Pianist();
        Trumpeter t1=new Trumpeter();
        musician m1;
        m1=p1;
        m1.play();
        m1=t1;
        m1.play();
       }
      }
      
      class Poly{
       public static void main(String[] args){
        Concert ct=new Concert();
       }
      }
      これを実行すると、
       play piano
       play trumpet
      となります。どちらも m1.play(); の結果です。m1にp1やt1を代入できることが、重要なポイントです。
      これだけですと、musicianの存在がありませんが、musician()にPianistとTrumpeterに共通したメソッドを追加すれば、スーパークラスとしての意味が出てきます。

    3. 抽象化
       上の例で、musicianのメソッドplay()を定義する意味はありません。そこで、抽象化をします。playメソッドをabstractとします。この場合、クラスもabstractとなります。このクラスを 継承 で利用します。

      abstract class musician{
       abstract void play();
      }
        
      class Pianist extends musician{
       public void play(){ System.out.println("play piano");}
        }
        
      class Trumpeter extends musician{
       public void play(){ System.out.println("play trumpet");}
       }
      
      class Concert{
       Concert(){
        Pianist p1=new Pianist();
        Trumpeter t1=new Trumpeter();
        musician m1;
        m1=p1;
        m1.play();
        m1=t1;
        m1.play();
       }
      }
      
      class Poly{
       public static void main(String[] args){
        Concert ct=new Concert();
       }
      }
      実行結果は同じですが、musicianのサブクラスを作成しplay()の定義を忘れた場合、コンパイルでエラーが出ます。

    4. 実装
       同じ例を、interfaceで実現します。この場合、implementsしたがわで、play() を実装しないとコンパイル時エラーになります。interface で定義できるのは 抽象メソッドと定数のみです。

      interface musician{
       abstract void play();
      }
        
      class Pianist implements musician{
       public void play(){ System.out.println("play piano");}
        }
        
      class Trumpeter implements musician{
       public void play(){ System.out.println("play trumpet");}
       }
      
      class Concert{
       Concert(){
        Pianist p1=new Pianist();
        Trumpeter t1=new Trumpeter();
        musician m1;
        m1=p1;
        m1.play();
        m1=t1;
        m1.play();
       }
      }
      
      public class Poly{
       public static void main(String[] args){
        Concert ct=new Concert();
       }
      }
    5. 利点
       多態性の利点は、主プログラムを上位クラスの抽象メソッドで記述できる点です。抽象メソッドを具体的なメソッドで置き換えるだけで、主プログラムの振る舞いが変化します。また、実行時に切り替えることも可能です。
       デザインパターンの多くは、この多態性を利用した作成されています。