15

Javaに次の階層クラスがあるとしましょう。

class A 
{
}
class B extends A
{
    public void m()
    {
        System.out.println("B\n");
    }
}
class C extends B
{
    public void m()
    {
        System.out.println("C\n");
    }
}
class D extends C
{
    public static void main(String[] args)
    {
        A a = new D();
        // a.m(); // doesn't work
        B b = new D();
        b.m();
        C c = new D();
        c.m();
        D d = new D();
        d.m();
    }
}

これは、C#での同じコードの(ブラインド)複製です。

using System;
class A 
{   
}
class B : A
{
    public void M()
    {
        Console.WriteLine("B");
    }
}
class C : B
{
    public void M() // I need to use public new void M() to avoid the warning
    {
        Console.WriteLine("C");
    }
}
class D : C
{
    public static void Main(String[] args)
    {
        A a = new D();
        // a.M(); // doesn't work       
        B b = new D();
        b.M();
        C c = new D();
        c.M();
        D d = new D();
        d.M();
    }
}

Javaコードを実行するとC-C-C、C#がを返すのに対して取得しB-C-Cました。

私にとって、参照Bは独自のメソッドを呼び出すため、C#の結果の方が理にかなっています。

  • C-C-C代わりに印刷するというJavaデザイナーの決定の背後にある論理は何B-C-Cですか?つまり、参照BがCでオーバーライドメソッドを使用するのはなぜですか?このアプローチの利点は何ですか?
  • B-C-CC#と同じようにJavaコードを変更して印刷するにはどうすればよいですか?つまり、Javaが使用する正確な参照のメソッドを呼び出すようにJavaに教えるにはどうすればよいですか?
  • 印刷するようにC#コードを変更するにはどうすればよいC-C-Cですか?つまり、オーバーライドメソッドを呼び出すようにC#に教えるにはどうすればよいですか?
4

4 に答える 4

13

これは、仮想関数の定義用です。

仮想関数または仮想メソッドは、継承クラス内で同じシグニチャを持つ関数によって動作をオーバーライドできる関数またはメソッドです。この概念は、オブジェクト指向プログラミング(OOP)のポリモーフィズム部分の非常に重要な部分です。

C#では、MSDNに示すように、オーバーライドするためにメソッドを仮想として宣言する必要があります。

Mメソッドは仮想ではないため、変数が実際にインスタンスであっても実行されますb.M()bD

Javaでは、すべての非静的メソッドはデフォルトで仮想であるため、メソッドをオーバーライドすると(@Overrideアノテーションがなくても)、の動作はメソッドの動作を継承するものb.M()になります。d.M()c.M()

C#と同じようにJavaコードを変更してBCCを印刷するにはどうすればよいですか?つまり、Javaが使用する正確な参照のメソッドを呼び出すようにJavaに教えるにはどうすればよいですか?

Javaではこれを行うことはできません。クラスのMメソッドは、のメソッドCをオーバーライドします。に修飾子を追加すると、それまたは他の子がメソッドをオーバーライドできなくなります。MBfinalB#MCBM()

C#コードを変更してCCCを印刷するにはどうすればよいですか?つまり、オーバーライドメソッドを呼び出すようにC#に教えるにはどうすればよいですか?

Mクラスのメソッドをに変更し、BクラスvirtualでオーバーライドしますC

class B : A
{
    public virtual void M()
    {
        Console.WriteLine("B");
    }
}
class C : B
{
    public override void M() // I need to use public new void M() to avoid the warning
    {
        Console.WriteLine("C");
    }
}
于 2012-11-10T15:03:05.033 に答える
8
  1. Javaでは、すべてのメソッドがデフォルトで仮想化されています。また、派生クラスのメソッドは、ベースのメソッドをオーバーライドします。C#ではそうではありません。

  2. あなたはこれを行うことができないようです。ただし、派生クラスがこのメソッドをオーバーライドするのを防ぐには、このメソッドをとして宣言しますfinal

  3. virtual基本クラスのキーワードとoverride派生クラスのキーワードを使用して、このメソッドを宣言します。

于 2012-11-10T14:59:30.407 に答える
1

BCCの代わりにCCCを印刷するというJava設計者の決定の背後にある論理は何ですか?

Javaは、デフォルトでメソッドを仮想化します。過去には、これは良い習慣であるという理解があり、Javaの誕生時には、おそらくその理解のピークにありました。

最近では、多くの人がそれに固執していますが、それには抵抗もあります(特に、仮想メソッドがクラスを予期しないサブクラス実装の選択に開放するため)。

(注:ここには正しいことも悪いこともありません。それぞれのアプローチには長所と短所があります。)

C#と同じようにJavaコードを変更してBCCを印刷するにはどうすればよいですか?

それらを宣言しますfinal

C#コードを変更してCCCを印刷するにはどうすればよいですか?

それらを宣言するvirtualabstract、それらを定義するクラス(B質問で)、および子クラスで宣言しoverrideます。

于 2012-11-10T15:00:42.833 に答える
0

BCCの代わりにCCCを印刷するというJava設計者の決定の背後にある論理は何ですか?つまり、参照BがCでオーバーライドメソッドを使用するのはなぜですか?このアプローチの利点は何ですか?

CクラスからMメソッドを継承したDクラスオブジェクトからメソッドを呼び出しているように見えます。Javaでは参照タイプは重要ではありません。重要な部分は、どのクラスがオブジェクトを参照しているかです。

于 2012-11-10T14:59:42.777 に答える