0

私は C# にまったく慣れていないので、私の質問がばかげているように聞こえる場合は、私の無知をご容赦ください。

-Inheritance Funda をで試してみたC#ところ、動作がおかしいことがわかったので、 でチェックしてみるとJava、期待どおりの結果が得られました。

-ここに欠けているものがあるか知りたいだけです........

C# コード:

 class Animal
 {
   public void Sound()
   {
     System.Console.WriteLine("I don't make any sound");
   }


 } 





 class Dog : Animal
 {
   public void Sound()
   {
     System.Console.WriteLine("barking");


   }  

 }


 class InheritTest
 {
   static void Main()
   {
     Animal a = new Dog();         // Implicit conversion

     Dog    d = (Dog) a;   // Explicit conversion


     a.Sound();
     d.Sound();

   }

 }

出力:

I don't make any sound
barking

ジャバコード:

 class Animal
 {
   public void sound()
   {
     System.out.println("I don't make any sound");
   }


 } 





 class Dog extends Animal
 {
   public void sound()
   {
     System.out.println("barking");


   }  

 }


 class InheritTest
 {
   public static void main(String[] args)
   {
     Animal a = new Dog();         // Implicit conversion

     Dog    d = (Dog) a;   // Explicit conversion


     a.sound();
     d.sound();

   }

 }

出力:

barking
barking

-今、このエピソード全体についての私の疑問は..C#私はタイプDog objectのオブジェクト参照変数に割り当てています.onメソッドを呼び出すと、(Dogクラスのオーバーライドされたメソッド)として出力を取得する必要がありますが、代わりにメソッドとして出力を与えて呼び出されます。aAnimalSound()abarkingAnimal's Sound()I don't make any sound

-しかし、Java物事は期待どおりに機能しています..継承はどこでも同じように機能します。

誰かが私を助けてくれるなら、私は義務付けられます...... よろしくお願いします。

4

3 に答える 3

5

最初の例では、既存のメソッドを実際にオーバーライドしているのではなく、隠しています。これは、従来のメソッドのオーバーライドとは異なる特別な C# メカニズムです。期待どおりに動作するように、ソース メソッドを as としてマークし、メソッドvirtualをオーバーライドします。ここに良い説明があります。それについて警告を受けていませんか?override

于 2014-05-05T05:39:34.293 に答える
3

メソッドはvirtualデフォルトで Java (IIRC) にあります。C# では、これは当てはまりません。

C# メソッドをvirtualおよびoverrideそれらとしてマークします。これにより、期待される出力が生成されます。

于 2014-05-05T05:40:56.793 に答える
0

コードを検討する

Animal a = new Dog();
a.sound();

サウンド メソッドを呼び出すために、ランタイムはまずオブジェクトの実際のタイプ (Dog) を解決してから、サウンド メソッドを呼び出す必要があります。メソッド (sound) が型 (Dog) に存在しない場合は、コンパイル時の型 (Animal) でメソッドを呼び出す必要があります。

ご覧のとおり、このプロセスには時間がかかり、パフォーマンスに影響を与える可能性があります。このプロセスをより効率的にするために、C# は「仮想テーブル」と呼ばれるものを使用しますが、Java はランタイム「動的ディスパッチ」と呼ばれる手法を使用します。これが意味することは、C# では、メソッドを仮想としてマークして、基になる型でルックアップを実行する必要があることをコンパイラに伝える必要があるということです。この方法では、実際にどのメソッドを呼び出す必要があるかをすべてのオブジェクトがチェックする必要がある場合よりも、プログラムが消費するメモリが大幅に少なくなり、実行が高速になります。ただし、これは、メソッドを検索するために仮想テーブルが必要であることをコンパイラに伝えるために、各メソッドを仮想としてマークする必要があることも意味します。

要するに設計思想の違いです。Java では、デフォルトですべての関数を仮想として設定することで、どの関数を仮想としてマークするかを気にすることなく、プログラマーがクラスを簡単に拡張できるようにしています。一方、C# では、機能を派生クラスでオーバーライドする場合は、関数を仮想としてマークする必要があります。これは、基本クラスの機能を意図せずオーバーライドするのを防ぐのにも役立ちます。(C# では、基本クラスのメソッドを仮想としてマークし、派生クラスでオーバーライドする必要があります)

于 2014-05-05T06:21:22.080 に答える