私は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.Object
ToString()
更新:私は最近、このトピックについて少し深く掘り下げたブログ投稿を書きました。こちらをご覧ください。
これで、「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
のメソッド宣言で削除すると、次のようになりますm1
B
override
S
m1
つまり、キャストにはm1
、基本クラスのメソッドの元の宣言B
が使用されるという効果もあります。
注new
: subclass でキーワードを使用している場合は、次のS
ようになります。
new public string m1() {
return "overridden m1";
}
virtual
基本クラスのキーワードが存在しないと仮定するとB
、出力が得られます
m1
同じように。にキャストしない場合はB
、新しいメソッドが使用されます。これは、メソッド (基本クラスの元のメソッド) のシャドウ(または非表示)と呼ばれます。
概要:
基本クラスにキャストした場合にも有効なメソッドをオーバーライドするには、基本クラスとサブクラスで
virtual
キーワードを使用します。override
サブクラスでのみアクティブにする必要があるメソッドをオーバーライドする場合は
new
、サブクラスのメソッド宣言でキーワードを使用します。これまで見てきたように、それがなくても機能しますが、これがメソッドの新しいバージョンであることを誰もが認識できるように、存在する方がよいでしょう。