【面接問題】多態の実現メカニズムは何ですか

8051 ワード

マルチステートは、オブジェクト向けプログラム設計におけるコード再利用の重要なメカニズムであり、同じ操作が異なるオブジェクトに作用すると、異なる意味があり、例えば、同じ「+」操作を実行し、「3+4」は整数加算を実現するために使用され、「3」+「4」は文字列の接続を実現する.Java言語では、マルチステートには主に次の2つの表現があります.
  • メソッドのオーバーロード(overload)とは、同じクラスに複数の同名のメソッドがあるが、これらのメソッドには異なるパラメータがあるため、コンパイル時にどのメソッドが呼び出されるかを決定することができ、コンパイル時にマルチステートである.オーバーロードは、1つのクラスにおけるメソッドマルチステートと見なすことができる.
  • メソッドの上書き(override)サブクラスは親のメソッドを上書きすることができるため、同じメソッドは親と子の間で異なる表現形式を持つことができます.java言語では、ベースクラスの参照変数はベースクラスのインスタンスオブジェクトだけでなく、そのサブクラスのインスタンスオブジェクトも指すことができます.同様に、インタフェースの参照変数は、実際のクラスのインスタンスオブジェクトも指すことができます.プログラム呼び出しのメソッド動的バインドは実行時のみ(バインディングとは、メソッド呼び出しとメソッド本体を接続することを意味する)は、変数が指す特定のインスタンスオブジェクトを参照する方法、すなわち、変数のタイプで定義されたメソッドを参照するのではなく、メモリ内で実行中のオブジェクトを参照する方法である.この動的バインディングの方法により、マルチステートが実現される.実行時にのみ呼び出される呼び出しのどちらが決定されるかメソッドであるため、メソッドオーバーライドによって実現されるマルチステートは、実行時マルチステートとも呼ぶことができ、例は以下の通りである:
  • class Base{
    	public Base(){
    		g();
    	}
    	public void f(){
    		System.out.println("Base f()");
    	}
    	public void g(){
    		System.out.println("Base g()");
    	}
    }
    class Derived extends Base {
    	public void f(){
    		System.out.println("Derived f()");
    	}
    	public void g(){
    		System.out.println("Derived g()");
    	}
    }
    public class Test{
    	public static void main(String[] args){
    		Base b = new Derived();
    		b.f();
    		b.g();
    	}
    }
    
    /*
           :
    Derived g()
    Derived f()
    Derived g()
    */
    

    上記の例では、子クラスDerivedのf()メソッドとg()メソッドは親クラスBaseのメソッドと同名であるため、DerivedのメソッドはBaseのメソッドを上書きする.Baseb=new Derived()文を実行すると、Baseクラスのコンストラクション関数が呼び出されますが、Baseのコンストラクション関数では、Java言語のマルチステート特性のため、親Baseのg()メソッドではなく、サブクラスDerivedのg()メソッドが呼び出されるため、Derived()が出力されます.実際にDerivedクラスのオブジェクトが作成されているため、後のメソッド呼び出しではサブクラスDerivedのメソッドが呼び出されます.
    また、クラス内のメソッドにのみ多態の概念があり、クラス内のメンバー変数には多態の概念がありません.例は以下のとおりです.
    class Base{
    	public int i = 1;
    }
    class Derived extends Base{
    	public int i = 2;
    }
    public class Test{
    	public static void main(String[] args){
    		Base b = new Derived();
    		System.out.println(b.i);
    	}
    }
    
    /*
           :
    1
    */
    

    このように、メンバー変数はマルチステートを実装できません.メンバー変数の値が親クラスであるかサブクラスであるかは、作成オブジェクトのタイプに依存せず、定義された変数のタイプに依存します.これは、コンパイル中に決定されます.上記の例では、bが属するタイプがBaseであるため、b.iはBaseクラスで定義されたiを指すため、プログラム出力結果は1である.