众所周知,对类中的方法使用 virtual 关键字允许我们在其派生子类中覆盖它。然而,方法仍然必须坚持相同的签名,例如返回值、参数等。
问题:在 C# 中,我如何也可以覆盖签名?这可能吗?
谢谢。
众所周知,对类中的方法使用 virtual 关键字允许我们在其派生子类中覆盖它。然而,方法仍然必须坚持相同的签名,例如返回值、参数等。
问题:在 C# 中,我如何也可以覆盖签名?这可能吗?
谢谢。
这不可能。但是,如果需要,您可以创建一个重载。
编辑
为了让我反对new
,请考虑您有一个基础对象以及从它继承的基础对象的情况。通过放置new
在您尝试“更改”方法签名的方法之前,您实际上是在浪费四个键击。
public class Base {
public string Foo () { return null; }
}
public class Inherited : Base {
public new int Foo () { return 0; }
}
现在,Inherited
有两种方法:
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);
}
您正在谈论创建一种新方法。如果名称相同,但参数不同(返回类型和参数的类型和参数数量),您实际上是在重载。