誰もが知っているように、クラスのメソッドに virtual キーワードを使用すると、その派生サブクラスでそれをオーバーライドできます。ただし、メソッドは、戻り値、引数など、同じ署名に固執する必要があります。
質問: C# では、どうすれば署名もオーバーライドできますか? これは可能ですか?
ありがとう。
誰もが知っているように、クラスのメソッドに virtual キーワードを使用すると、その派生サブクラスでそれをオーバーライドできます。ただし、メソッドは、戻り値、引数など、同じ署名に固執する必要があります。
質問: C# では、どうすれば署名もオーバーライドできますか? これは可能ですか?
ありがとう。
それは不可能。ただし、必要に応じてオーバーロードを作成できます。
編集
に対して私new
の主張をするために、基本オブジェクトとそれを継承するオブジェクトがある場合を考えてください。new
メソッド シグネチャを「変更」しようとしているメソッドの前に配置すると、実際には 4 つのキー ストロークが無駄になります。
public class Base {
public string Foo () { return null; }
}
public class Inherited : Base {
public new int Foo () { return 0; }
}
現在、次のInherited
2 つの方法があります。
public string Foo () { return null; }
public int Foo () { return 0; }
メソッドのシグネチャを実際に変更しているわけではありません。したがって、new
キーワードは必要ありません。それがなくても同じ効果が得られます:
public class Inherited : Base {
public int Foo () { return 0; }
}
の使用は、基本クラスの非仮想メンバーnew
をオーバーライドすることです。
public class Base {
public string Foo () { return null; }
}
public class Inherited : Base {
public new string Foo () { return "Something else..."; }
}
しかし、この微妙な点に注意を払わないと、これで問題が発生します。virtual
関数を正しい呼び出しにマップする仮想ルックアップ テーブルを取得します。ではnew
、そうではありません。Inherited
オブジェクトが必要な場所を渡すBase
と (これはもちろん機能します)、Base
クラスのオブジェクトがFoo()
呼び出されます! Inherited
の「オーバーライド」ではありませんFoo()
。
これは、仮想メンバーのオーバーライドと同じ動作ではありません。
public static class MyClass {
public string MyMethod (Base @base) {
return @base.Foo ();
}
}
[Test]
public void then_it_should_return_non_null () {
var obj = new Inherited ();
var result = MyClass.MyMethod(obj); // obj will get upcasted to Base
Assert.That (result, Is.EqualTo(obj.Foo ())); // Assert fails!
}
[Test]
public void inherited_should_return_correct_value ()
{
var obj = new Inherited ();
var result = obj.Foo (); // will access the "new" method, hiding Base's implementation
Assert.That (result, Is.Not.Null); // Assert passes!
}
new
キーワードを使用して、古い実装を非表示にすることができます。ただし、基本クラスはそれを見ることができません。
class Base {
public string Foo() { }
}
class Sub : Base {
new public int Foo() { }
}
new
呼び出し署名が同じ場合にのみ必要です。
その時点で、あなたは新しいメソッドを作成しているだけです。しかし、単純に新しいメソッド シグネチャを使用して新しいメソッドを作成したい場合は、base.OtherMethod(param1, param2)... を呼び出します。
私がしようとしているポイントは、基本クラスと同じ名前のメソッドを作成するつもりであるが、署名が異なるが、それでも基本クラスを呼び出したい場合は、できるということです。
例えば:
// In base class - note, the "virtual" isn't necessary.
public virtual void PostMessage(string message, DateTime entryDate) { ... }
次に、「ああ、この基本クラスに、日付を必要としないメソッドのオーバーロードがあればいいのに…どうすればいいの?!」と考えます。
// In your sub-class.
public void PostMessage(string message)
{
base.PostMessage(message, DateTime.Now);
}
新しいメソッドの作成について話している。名前は同じでもパラメーターが異なる場合 (戻り値の型とパラメーターの型とパラメーターの数)、実際にはオーバーロードしています。