【发布时间】:2012-10-19 01:01:48
【问题描述】:
众所周知,对类中的方法使用 virtual 关键字可以让我们在其派生的子类中覆盖它。但是,方法仍然必须坚持相同的签名,例如返回值、参数等。
问题:在 C# 中,我如何也可以覆盖签名?这可能吗?
谢谢。
【问题讨论】:
标签: c#
众所周知,对类中的方法使用 virtual 关键字可以让我们在其派生的子类中覆盖它。但是,方法仍然必须坚持相同的签名,例如返回值、参数等。
问题:在 C# 中,我如何也可以覆盖签名?这可能吗?
谢谢。
【问题讨论】:
标签: 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的用法是override a non-virtual member of a base class:
public class Base {
public string Foo () { return null; }
}
public class Inherited : Base {
public new string Foo () { return "Something else..."; }
}
但是如果你不注意这个微妙之处,你会遇到这个问题。使用virtual,您将获得一个虚拟查找表,它将您的函数映射到正确的调用。使用new,您不会。如果您在需要Base 对象的地方传入Inherited(这当然可以),则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);
}
【讨论】:
您正在谈论创建一个新方法。如果名称相同,但参数不同(返回类型和参数的类型和参数个数),您实际上是在重载。
【讨论】: