Javaオブジェクト向けプロパティの多態性


たじょうたいせい
オブジェクト向け(OOP)の3つの特性:カプセル化、継承、マルチステート.
マルチステート(polymorphism)とは、同じ動作が複数の異なる表現形式を有することを意味し、オブジェクト向けプログラム設計において同じメッセージとして表現されることは、送信オブジェクトのタイプによって異なる動作を行うことができる.
マルチステートの利点
多態性はタイプ間の結合関係をある程度解消することができ,統一インタフェース方式により異なるクラスのオブジェクトを直接置き換えることができ,プログラムがより柔軟で拡張可能である.
オブジェクト向けのマルチステートの存在に必要な3つの条件
  • 継承
  • 書き換え
  • 親参照は、子オブジェクト
  • を指す.
    マルチステートの実現方式
    オーバーライド(Override)とリロード(Overload)
    静的多態性:メソッドリロード(Method Overloading)
    メソッドリロード(Method Overloading)では、クラスに同じ名前のメソッドを複数作成できますが、メソッドパラメータのリストが異なります.
    リロード形式:
    Case 1:パラメータ数変化(有効)
    add(int, int)
    add(int, int, int)

    Case 2:パラメータデータ型変化(有効)
    add(int, int)
    add(int, float)

    Case 3:パラメータデータ型の順序変化(有効)
    add(int, float)
    add(float, int)

    bad case 1:戻りタイプのみ変更(無効)
    int add(int, int)
    float add(int, int)

    Javaメソッド署名は、メソッド名とその後のパラメータリストによって決定され、戻りタイプコンパイラを変更するだけでは再ロードできません.ただし、メソッドリロード(Method Overloading)では、戻りタイプとアクセス権限を変更できますが、メソッド署名には含まれません.
    メソッドリロード(Method Overloading)式多様性、すなわちメソッド呼び出しは、呼び出し時に伝達されるパラメータ(数、タイプ、順序)に依存し、コンパイル時の静的多様性に属する.
    ダイナミックマルチステート:メソッド書き換え(Method Overriding)メソッド書き換えMethod Overriding
    メソッド書き換え(Method Overriding)では、サブクラスが親にアクセスできるメソッドを使用してカスタム動作を実現できますが、メソッド署名は一貫性を保つ必要があります.書き換えの利点は、親コードを変更することなく、サブクラス継承のメソッドを変更できることです.
    書き換え形式:依存継承を書き換え、親参照によって子オブジェクトに動的多様性を実現します.
    public class Animal{
       public void sound(){
          System.out.println("Animal is making a sound");   
       }
    }
    
    public class Cat extends Animal{
        @Override
        public void sound(){
            System.out.println("Meow");
        }
        
        public static void main(String args[]){
            Animal obj = new Cat();
            obj.sound();
        }
    }

    出力:
    Meow

    上書き(上書き)ルール:
  • メソッド署名(メソッド名とパラメータリスト)は同じでなければなりません.戻りタイプは互換性が必要です.
  • では、メソッドのアクセス権限を低下させることはできません.
  • static,private,finalタグの方法およびクラスの構造方法は書き換えられない(上書き).
  • 解析理由:Javaはメソッドによってメソッドを署名して識別するため、書き換えるにはサブクラスが親クラスから継承されていることを確認する同じメソッドが必要です.
    子クラスは親メソッドのアクセス権限(可視性)を下げることはできませんが、アップグレードできます.継承は「is a」関係を反映し、子クラスは親クラスであり、親クラスのすべての対外開放的な行為をサポートします.メソッドのアクセス権限を下げ、親が統一インタフェース方式としてメソッドを呼び出す能力が破壊されます.
    private,finalタグのメソッドおよび親クラスの構造メソッドは継承できないため,書き換えることができない.
    staticタグのメソッドは静的メソッドがクラスに属し、 . 形式で呼び出され、オブジェクトに依存する必要はありません.静的メソッドと属性はクラスによって継承され、サブクラスは同じ名前の静的メソッドと属性を定義することができ、インスタンスメソッド「書き換え」と属性「再名」とは異なり、「非表示」と呼ばれます.このとき、サブクラスで同じ名前の親の静的メソッドと属性が呼び出され、 . または . を指定する必要があります.
    静的バインドと動的バインド
    マルチステート性のタイプは、実行時とコンパイル時に分けられ、メソッド書き換え(Method Overriding)は実行時の動的マルチステート性を表し、メソッドリロード(Method Overloading)はコンパイル時の静的マルチステート性を表す.
    メソッド呼び出しとメソッドボディの関連付けはバインディングと呼ばれ、コンパイル時に発生する静的バインディング(Static Binding or Early Binding)と実行時に発生する動的バインディング(Dynamic Binding or Late Binding)の2種類がある.
    static,private,finalタグのメソッドおよびクラスの構築メソッドは静的にバインドされており,コンパイル時に所属するクラスのタイプを決定するため,これらのメソッドは上書きできない.他の非タグの方法は「虚関数」と呼ぶことができ、Javaには「虚関数」の概念はありません.すべての一般的な関数(メソッド)のデフォルトはC++の「虚関数」に相当し、オーバーライド(Override)が可能であるため、虚関数(Virtual Method)は、実行時の特定のオブジェクトのタイプに応じて動的バインドを行い、メソッド書き換え(Method Overriding)などの動的多様性を実現することができる.
    静的バインドの例:
    class Human{
       public static void walk()
       {
           System.out.println("Human walks");
       }
    }
    class Boy extends Human{
       public static void walk(){
           System.out.println("Boy walks");
       }
       public static void main( String args[]) {
           /* Reference is of Human type and object is
            * Boy type
            */
           Human obj = new Boy();
           /* Reference is of Human type and object is
            * of Human type.
            */
           Human obj2 = new Human();
           obj.walk();
           obj2.walk();
       }
    }

    出力:
    Human walks
    Human walks

    staticとして宣言する方法は書き換えることはできませんが、再宣言(非表示)することができます.
    Static Binding vs Dynamic Binding
  • 静的バインディングはコンパイル時に発生し、動的バインディングは実行時に発生する.
  • 静的バインドはクラス情報:クラスのタイプ決定呼び出し方法を使用し、動的バインドはオブジェクト情報:オブジェクトのタイプ決定呼び出し方法を使用する.
  • メソッドは静的バインドを再ロードし、メソッドは動的バインドを書き換えます.

  • 総合練習
    マルチステートサンプル:
    class A {
        public String show(D obj) { //    
            return ("A and D");
        }
    
        public String show(A obj) { //    
            return ("A and A");
        }
    }
    
    class B extends A {
        public String show(B obj) { //    
            return ("B and B");
        }
    
        public String show(A obj) { //    
            return ("B and A");
        }
    }
    
    class C extends B {
    }
    
    class D extends B {
    }
    
    public class Main {
    
        public static void main(String[] args) {
            A a1 = new A();
            A a2 = new B();
            B b = new B();
            C c = new C();
            D d = new D();
            System.out.println("1--" + a1.show(b));
            System.out.println("2--" + a1.show(c));
            System.out.println("3--" + a1.show(d));
            System.out.println("4--" + a2.show(b));
            System.out.println("5--" + a2.show(c));
            System.out.println("6--" + a2.show(d));
            System.out.println("7--" + b.show(b));
            System.out.println("8--" + b.show(c));
            System.out.println("9--" + b.show(d));
        }
    }

    実行結果:
    1--A and A
    2--A and A
    3--A and D
    4--B and A
    5--B and A
    6--A and D
    7--B and B
    8--B and B
    9--A and D

    詳細分析:
    A、B、C、Dの各種類の継承関係を図に示す.
  • A a1 = new A();はオブジェクトa 1を正常に作成し、関数リロードshow()に関し、a 1はメソッド1 show(D obj)とメソッド2 show(A obj)を呼び出す能力を有する.a1.show(b)は、コンパイラによって静的バインディング(前期バインディング)方法2 show(A obj)を行う.
  • a1.show(c)コンパイラによる静的バインディング(前期バインディング)メソッド2 show(A obj).
  • a1.show(d)コンパイラによる静的バインド(前期バインド)方法show(D obj).
  • A a2 = new B();多態は親参照を作成し、子オブジェクトを指し、a 2のアップシフトは、Aクラスメソッド1 show(D obj)とメソッド2 show(A obj)を呼び出す能力を有し、子クラスBが親クラスAを書き換えるメソッド2 show(A obj)はメソッド4 show(A obj)である.アップシフトには欠点があることを覚えておいてください.すなわち、サブクラスには、メソッド3 show(B obj)のような親にはないメソッドが呼び出されません.a2.show(b)実行時動的バインド(後期バインド)メソッド四show(A obj).
  • a2.show(c)実行時動的バインド(後期バインド)メソッド四show(A obj).
  • a2.show(d)コンパイラによる静的バインド(前期バインド)方法show(D obj).
  • B b = new B();は、通常、オブジェクトbを作成し、関数リロードshow()に関し、bは、メソッド3 show(B obj)とメソッド4 show(A obj)を呼び出す能力を有する.同時にBは、Aから継承されるので、方法1 show(D obj)と方法2 show(A obj)とを有し、方法2は、方法4によって上書きされる.b.show(b)コンパイラによる静的バインド(前期バインド)方法三show(B obj).
  • b.show(c)コンパイラによる静的バインディング(前期バインディング)方法三show(B obj).
  • b.show(d)コンパイラによる静的バインド(前期バインド)方法show(D obj).