0

私はそれを完全に理解しようと試みるために継承で遊んでいます:

プライベートメソッドを使用して親クラスを作成し、それを子クラスでオーバーライドしてパブリックにしました。また、クラスごとに異なる方法でtoStringメソッドをオーバーライドしました。このように見えます:

public class testparent {
    public String toString(){
        return ("One and two boobaloo");
    }
    private void hitMe(){
        System.out.println("BAM");
    }
}

public class testbaby extends testparent{
    public String toString() {
        return "Bananas";
    }
    public void hitMe(){
        System.out.println("BAMBAM");
    }
    public static void main(String[] args){
        testbaby testy = new testbaby();
        testparent test2 = testy;
        System.out.println(test2);
        //test2.hitMe(); //????? not allowed
        System.out.println(testy);
        testy.hitMe();
    }
}

さて、なぜ両方のオブジェクトを印刷すると「バナナ」が生成されるのに、両方のクラスのhitMe()メソッドを使用できないのですか?

4

2 に答える 2

5

これは、メソッドの動的バインディングと言語自体の静的型付けによるものです。

何が起こるかというと、Javaは静的に型付けされており、動的バインディングを持っているので、次のようになります。

  • メソッドは宣言された変数hitMeでのみ呼び出すことができます。これは、メソッドがtestbabyプライベートでtestparentあるためです。静的型付けのため、Javaは、メソッドが実行時に確実に呼び出されるようにする必要があります。
  • メソッドtoStringは両方のオブジェクトで呼び出すことができ(から継承されているためObject)、実行時にどちらが効果的に呼び出されるかは、変数宣言ではなく、実行時インスタンスに従って選択されます(動的バインディングのため)

動的バインディングの方法論によれば、メソッドの正しい実行時の実装は、宣言されたオブジェクトではなく、オブジェクトの実際のインスタンスに従って実行時に選択されます。

これは、として宣言test2した場合testparentでも、それはtestbabyオブジェクトであるということを意味します(インスタンスを割り当てているためtestbaby)。実行時に、正しい実装は子の1つになります。

testbaby ただし、aはであるため、これは完全に合法ですtestparent

于 2012-04-19T20:23:10.117 に答える
3

基本的に、test2型の変数であると宣言すると、「実際に」であるtestparent知識を意図的に破棄しているためです。 test2testbaby

これは継承のポイントの一部です。を使用するコードは、それがまたはのサブクラスであるtest2と想定することのみが許可されており、そのコードは、オブジェクトではないオブジェクトも含め、すべてのオブジェクトに対して機能する必要があります。testparenttestparent testparenttestbaby

参考までに、外部testParentに関する限り、このtestParent.hitMe()方法は存在しません(この段階で心配する必要のない、いくつかの邪悪な反射ベースのものを除いて)。方法さえtestbaby知らないtestParent.hitMe()

于 2012-04-19T20:21:08.567 に答える