40

ここで動作しているJavaコード

class Cup {
    public String sayColor() {
        return "i have a color .";
    }
}

class TCup extends Cup{
    public String sayColor(){
        System.out.println(super.getClass().getName());
        return super.sayColor()+"color is tee green.";
    }
}

class MyTCup extends TCup {
    public String sayColor(){
        System.out.println(super.getClass().getName());
        return super.sayColor()+"but brushed to red now!";
    }
}
class Test {
    public static void main(String[] args) {
        Cup c = new MyTCup();
        System.out.print(c.sayColor());
    }
}

Testクラスの印刷を実行します

MyTCup
MyTCup
i have a color .color is tee green.but brushed to red now!

質問1:実行時のオブジェクトCのタイプはMyTCupですが、常にスーパーメソッドを呼び出すことができます。オブジェクトを初期化した後、MyTCup内のメモリにメソッドスタックがあり、実行時にコードのように呼び出すことができますか?

質問2:他のオブジェクトでスーパーメソッドを呼び出す方法はありません。私が知っているように、c++はいつでも親メソッドを呼び出すためにキャストできます。なぜJavaと違うのですか?

4

4 に答える 4

79

他のオブジェクトでスーパーメソッドを呼び出すことはできません-カプセル化に違反します。重要なのは、オブジェクトがオーバーライドされたメソッドの動作を制御するということです。たとえばadd、特定の状況で例外をスローするようにコレクションのメソッドをオーバーライドして、「有効な」アイテムのみがコレクションに追加されるようにすることができます。発信者がキャストでそれをバイパスできれば、それは無意味です!

オブジェクトがsuper.foo()それ自体を呼び出すことができる唯一の理由は、親実装を使用して1つの呼び出しを実装できるようにするためです。それが賢明にのみ行われるようにするのは、クラスのコード次第です。繰り返しになりますが、コレクションへの追加の例をとると、コレクションがオーバーライドaddする場合、検証済みのアイテムをコレクションに追加する何らかのsuper.add()方法が必要になります。これは、で行います。

カプセル化の同じ理由で、親の実装のみを呼び出すことができ、祖父母の実装は呼び出すことができないことに注意してください。super.foo()有効ですが、そうでsuper.super.foo()はありません。

于 2009-06-23T14:28:20.227 に答える
1

1:

あなたの質問ははっきりしていません。「コードのように実行時に呼び出す」とはどういう意味ですか?インスタンスcがそのスーパークラスをどのように認識しているかを尋ねている場合は、そうです。クラス階層はメモリに格納されており、VMからアクセスできます。

2:

Javaでは、実際にはインスタンスをその親にキャストできます。インスタンスでメソッドを呼び出すと、コンパイル時のクラスではなく、常にインスタンスの実際のクラスが使用されるだけです。つまり、Javaでは、すべてのメソッドはC++では「仮想」と呼ばれるものです。なぜこれが決まったのかわかりません。

編集:実際、Jon Skeetは、サブクラスのインスタンスでスーパークラスのメソッドを呼び出せない理由を非常にうまく説明しているので、今ではわかりました:-)。

于 2009-06-23T14:31:58.893 に答える
1

サブクラスで新しいヘルパー メソッドを定義して、元のメソッドをオーバーライドしないようにすることができます。それを呼び出すと、必要に応じてスーパー メソッドを呼び出すかどうかを指定できます。

于 2011-07-18T18:24:00.717 に答える
0

実際には可能ですが、方法論を使用する必要があるため、コードでのみ機能します。
スーパー クラスで、次のようにパラメータ「Class」をメソッドに追加します。

public String sayColor(Class classFilter){...

現在、すべてのオーバーライドで、現在のサブクラスが次のような指定されたフィルターの 1 つであるかどうかを確認します。

if(TCup.class!=classFilter)return super.sayColor(classFilter);
return "some text for TCup only";

私は排他的な方法でコーディングしました。さらにパラメーターを追加したり、null と比較したりできるため、結果をスーパークラスと結合し、創造性を発揮できます:)

于 2016-09-25T22:14:50.653 に答える