私はJavaの知識があり、ここ数日間C#を学んでいます。ここで、このリンクで提案されているように、対応するメソッド、プロパティなどをサブクラスでオーバーライドできるようにするために使用される「virtual」キーワードに出くわしました。これで、「virtual」キーワードを使用しなくてもメソッドをオーバーライドできると思います。では、なぜそれが必要なのでしょうか。
5 に答える
サブクラスのメソッドvirtualが本当に必要な場合は、キーワードが必要です。そうしないと、キーワードoverrideで宣言した場合と同じように、基本実装が新しい実装によって非表示になります。new
基本メソッドを宣言せずにメソッドを「オーバーライド」して非表示にすると、virtual多態性がなくなります。つまり、特殊なバージョンを「基本」バージョンに「キャスト」してメソッドを呼び出すと、代わりに常に基本クラスの実装が使用されます。オーバーライドされたバージョンの-これはあなたが期待するものではありません。
例:
class A
{
public void Show() { Console.WriteLine("A"); }
}
class B : A
{
public void Show() { Console.WriteLine("B"); }
}
A a = new A();
B b = new B();
a.Show(); // "A"
b.Show(); // "B"
A a1 = b;
a1.Show(); // "A"!!!
virtualメソッドにデフォルトの実装があることを定義する方法ですが、その実装は子クラスでオーバーライドされる可能性があります。仮想を使用する以外に、キーワードを使用せずにメソッドを直接オーバーライドすることはできませんnew(これは一般的に悪い習慣です)。
の実装の良い例はvirtualメソッドToString()です。すべてのオブジェクトは仮想メソッドを含むToString()基本クラスから継承するため、C#のすべてのオブジェクトは呼び出すことができることが保証されています。ただし、派生クラスはこれをオーバーライドして、オブジェクトのユーザーにとってより便利な独自の実装を提供できます。System.ObjectToString()
更新:私は最近、このトピックについて少し深く掘り下げたブログ投稿を書きました。こちらをご覧ください。
これで、「virtual」キーワードを使用しなくてもメソッドをオーバーライドできると思います。
いいえ、できません。Javaとは異なり、C#では、メンバーはデフォルトで封印さvirtualれており、キーワードでマークしない限り、メンバーをオーバーライドすることはできません。
次の例を見てください。
void Main()
{
var o1 = new S();
Console.WriteLine(((B)o1).m1());
}
public class B
{
public virtual string m1() {
return "m1";
}
}
public class S : B
{
override public string m1() {
return "overridden m1";
}
}
この例では、サブクラスSがインスタンス化され、オブジェクト variable に割り当てられますo1。ステートメントのConsole.WriteLineパラメーターでは、基本クラスにキャストされてBから、メソッドm1が呼び出されます。virtual基本クラスBとoverrideサブクラスで使用したためS、取得しています
オーバーライドされた m1
出力として。inおよびin サブクラスvirtualのメソッド宣言で削除すると、次のようになりますm1BoverrideS
m1
つまり、キャストにはm1、基本クラスのメソッドの元の宣言Bが使用されるという効果もあります。
注new: subclass でキーワードを使用している場合は、次のSようになります。
new public string m1() {
return "overridden m1";
}
virtual基本クラスのキーワードが存在しないと仮定するとB、出力が得られます
m1
同じように。にキャストしない場合はB、新しいメソッドが使用されます。これは、メソッド (基本クラスの元のメソッド) のシャドウ(または非表示)と呼ばれます。
概要:
基本クラスにキャストした場合にも有効なメソッドをオーバーライドするには、基本クラスとサブクラスで
virtualキーワードを使用します。overrideサブクラスでのみアクティブにする必要があるメソッドをオーバーライドする場合は
new、サブクラスのメソッド宣言でキーワードを使用します。これまで見てきたように、それがなくても機能しますが、これがメソッドの新しいバージョンであることを誰もが認識できるように、存在する方がよいでしょう。