2

クラスが別のクラスを拡張すると、スーパークラスのすべてのメソッドと変数が継承されます。メソッドと変数の両方をサブクラスで異なる方法で使用できます。これは、同じシグネチャを使用してサブクラスで異なる方法で定義する場合です。現在、Oracle は上書きと非表示を区別しています (http://docs.oracle.com/javase/tutorial/java/IandI/override.html)。インスタンス メソッドはそのスーパークラスのメソッドを上書きし、クラス メソッドはそれを隠します。「隠蔽とオーバーライドの違いには重要な意味があります。呼び出されるオーバーライドされたメソッドのバージョンは、サブクラスのものです。呼び出される隠しメソッドのバージョンは、それがスーパークラスから呼び出されるかサブクラスから呼び出されるかによって異なります。」

Yes と Maybe の 2 つのクラスがあるとします。はい、たぶん伸びます。多分文字列 a を持っています。

class Maybe {
    String a;
    public static void printOut() {
        System.out.println("Maybe");
    }
    public void printAndSet() {
        a = "Maybe";
        System.out.println(a);
    }

}
class Yes extends Maybe {
    public static void printOut() {
        System.out.println("Yes");
    }
    pubilc void printAndSet() {
         a = "Yes";
    }
}
class Print{
    public static void mail(String[] args) {
        Maybe m = new Maybe();
        Yes y = new Yes();
        Maybe.printOut();
        Yes.printOut();
        m.printAndSet();
        y.printAndSet();
}

そして私は言います:それはおそらくはい多分はい印刷されます

しかし、Oracle の記事を読んだ後、印刷する必要があると思いました。

yes
yes
maybe
yes

インスタンス メソッドがそのスーパークラス メソッドを上書きするためです。

私は出力に正しいと確信していますが、オラクルの方がよく知っているので、記事を理解していなかっただけだと思います. スーパークラスのオブジェクトからインスタンス メソッドを呼び出すと、上書きされたメソッドが使用されるということはあり得ません。上書きと非表示を区別する理由がわかりません!誰か助けてくれませんか?

編集; クラスを説明する代わりにコードを挿入しました!

4

3 に答える 3

5

静的メソッドはまったくオーバーライドできません。クラスのインスタンスではなく、クラス自体に対して作用するため、ポリモーフィックに呼び出されることはありません。

を呼び出すと、 で定義されMaybe.printOut()た静的メソッドが呼び出されます。に定義されたメソッドもあるという事実は関係ありません。これら 2 つのメソッドには、名前を除いて共通点はありません。printOut()MaybeprintOut()Yes

プログラムを作成して実行するだけで、疑問を確認または確認できることに注意してください。

メソッドの非表示に関する問題は、オブジェクトのインスタンスで静的メソッドの呼び出しを開始したときにのみ発生します。これは非常に悪い習慣であり、決して行うべきではありません。この規則を尊重せず、次の場合:

Maybe m = new Maybe();
Maybe y = new Yes();

m.printOut(); // DON'T DO THAT: it should be Maybe.printOut();
y.printOut(); // DON'T DO THAT: it should be Maybe.printOut() or Yes.printOut();

結果は になりますmaybe maybe。静的メソッドの場合、重要なのはオブジェクトの具象型 (および) ではなく、宣言された型 (および) であるためです。MaybeYesMaybeMaybe

于 2012-07-30T11:13:18.063 に答える
1
public class Parent {

    public String test(){
        return "p";
    }

    public static String testStatic(){
        return "sp";
    }
}


public class Child extends Parent {

    public String test(){
        return "c";
    }

    public static String testStatic(){
        return "sc";
    }
}

public class Demo{

    public static void main(String[] args) {

        Parent p =new Parent();
        Child c = new Child();
        Parent pc = new Child();

        System.out.println(p.test());
        System.out.println(c.test());
        System.out.println(pc.test());

            //Although this is not the correct way of calling static methods
        System.out.println(p.testStatic());
        System.out.println(c.testStatic());
        System.out.println(pc.testStatic());
    }
}

OUTPUT は次のようになります: - (静的メソッドとインスタンス メソッド)

p c c sp sc sp

于 2012-07-30T11:25:31.180 に答える
0

あなたの例に基づいて、次の例を見てください。

public class SO11720216 {
    static class Maybe {
        public static void hidden() { System.out.println("static maybe"); }
        public void overwritten() { System.out.println("instance maybe"); }
        public void inherited() { hidden(); }
        public void called() { overwritten(); inherited(); }
    }
    static class Yes extends Maybe {
        public static void hidden() { System.out.println("static yes"); }
        public void overwritten() { System.out.println("instance yes"); }
    }
    public static void main(String[] args) {
        Maybe m = new Maybe();
        Yes y = new Yes();

        m.called(); /* prints:
                       instance maybe
                       static maybe
                    */

        y.called(); /* prints:
                       instance yes
                       static maybe
                    */
        Yes.hidden(); /* prints: static yes */
        y.hidden(); /* bad style! prints: static yes */
    }
}

への呼び出しoverwrittenは、各派生クラスによって上書きされます。したがって、すべてのメソッドは現在のオブジェクトに属する実装を使用します。一方、への呼び出しhiddenは常に定義クラスの実装を使用します。したがって、Maybe.called常に を呼び出しMaybe.hidden、決してを呼び出しませんYes.hidden。を呼び出すYes.hiddenには、 のメソッド内からYes、または修飾名を使用して行う必要があります。

これを別の言い方をすると、次のようになります。

  • メソッドを上書きするとは、派生クラスのオブジェクトでメソッドが呼び出されるたびに、新しい実装が呼び出されることを意味します。
  • メソッドを非表示にするということは、このクラスのスコープ (つまり、そのメソッドのいずれかの本体、またはこのクラスの名前で修飾されている場合) でのその名前への非修飾呼び出し (上記の例hidden()のメソッドでの呼び出しのように) を意味します。 inherited()) は完全に異なる関数を呼び出すようになり、親クラスから同じ名前の静的メソッドにアクセスするための修飾が必要になります。

おそらく、基本クラスのオブジェクトであっても、上書きがメソッドへのすべての呼び出しに影響を与えると想定したという事実から、混乱が生じています。

于 2012-07-30T11:19:09.197 に答える