我想在抽象类中使用确切名称初始化虚拟方法。
在类中,这是继承器覆盖方法,我可以覆盖:
为了告诉你,我真正想要做的就是像这样:
abstract class A
{
public virtual void Func1() { }
}
class B : A
{
override string Func1(int a, int b)
{
return (a + b).ToString();
}
}
我知道,C#需要在基类中使用返回类型/ args,但在这种情况下可能会有一些关键字new
的提示吗?
答案 0 :(得分:3)
您只能override
确切的名称和参数。您可以new
无论您想要什么,但这都不会覆盖 - 只是隐藏在完全匹配的情况下。
我认为在你的情况下,你要么想为所有可能的组合创建重载,要么创建一个基本的抽象方法,它采用可以包含你想要的参数的单一类型。
示例:
public abstract void Func1( MyArgumentsType input );
现在派生类被强制覆盖一个方法,但是你可以将一组强大的参数传递给可以处理更多场景的方法。
多态性在这里对您有利,因为您可以将派生的参数类型传递给具有特定于情境的属性的方法。当然,这需要实现方法来理解更多派生的参数类型。
答案 1 :(得分:3)
你不能这样做。覆盖方法需要具有完全相同的签名,其中包括参数和返回类型。您无法告诉编译器使用不同的参数和返回类型覆盖方法。
如果您需要多态行为,则需要具有兼容的签名。否则编译器无法保证,将以多态方式找到所需的方法。
没有可以将签名void Func1()
和string Func1(int a, int b)
视为多态的可比方法。您可以使用内部传递lambdas的out
参数来概括它们,但无论如何 - 利用您需要的多态行为将它们带到一个公共签名。
答案 2 :(得分:3)
方法覆盖意味着修改继承成员的虚拟实现而不是签名。正如您所指出的,new
关键字将隐藏基类的具有相同名称的成员实现。但是,它只是可选的,请看一下这个benefit of using new keyword in derived class member having same name with base class member
答案 3 :(得分:3)
您希望实现类似于ToString
方法的行为,该方法针对不同类型(例如.ToString()
和float.ToString("c")
)具有许多不同的风格。
在这种情况下,ToString
的不同实现不是Object.ToString
的实现,而是基于参数适当解析的派生对象的常规附加方法。所有派生类最终都有一个虚拟ToString
方法(来自基类,可能在当前类中实现)以及可选的其他非虚拟方法。
请注意,在函数解析时考虑的C#结果类型更新,因此您不能真正拥有2个具有相同名称和相同参数的函数,并且期望“正确”选择一个函数。如果两者同时可见,则会出现编译时错误。方法前面的new
关键字只对该类(和派生的)可见该方法,并使用相同的签名隐藏基类方法。不幸的是,当使用包含派生类的基类的变量来调用这个方法时,这样做几乎可以保证很多混乱 - 尽管所有努力都要隐藏它,但是会调用基类中的虚拟方法。
答案 4 :(得分:1)
想一想......它将如何运作?假设您有一个静态类型为A
但动态类型为B
的引用,如下所示:
foo(B b) { bar(b); }
bar(A a) {
}
覆盖背后的想法是你在super / base上调用一个方法,然后它解析为重写的实现。按照这种逻辑,您应该能够bar
致电a.Func1()
,并且应该调用B
中的方法:
a.Func1(???)
但由于缺少参数,这里不可能。
存在参数逆变和返回类型协方差的概念; here在SO中是一个有趣的答案,链接到Eric Lippert的帖子应该是一个有趣的读物。