2

我想在抽象类中用确切的名称初始化虚拟方法。

在类中,这是继承者覆盖方法,我可以覆盖:

  • 基本方法的返回类型
  • 方法的参数

为了向您展示,我真正想做的是这样的:

abstract class A
{
    public virtual void Func1() { }
}

class B : A
{
    override string Func1(int a, int b)
    {
         return (a + b).ToString();
    }
}

我知道,C# 需要在基类中使用返回类型/参数,但在这种情况下可能有一些关键字提示new

4

5 回答 5

4

您只能override提供确切的名称和参数。你可以new随心所欲,但这并不是压倒一切的——只是在完全匹配的情况下隐藏。

我认为在您的情况下,您要么希望为所有可能的组合创建重载,要么创建一个单一的基本抽象方法,该方法采用可以包含所需参数的单一类型。

例子:

public abstract void Func1( MyArgumentsType input );

现在派生类被迫重写一个方法,但您可以将一组健壮的参数传递给可以处理更多场景的方法。

多态在这里对您有利,因为您可以将派生的参数类型传递给具有特定于情况的属性的方法。当然,这需要实现方法理解更多派生的参数类型。

于 2013-01-07T18:18:35.867 回答
3

你不能这样做。重写方法需要具有完全相同的签名,包括参数和返回类型。您无法告诉编译器使用不同的参数和返回类型覆盖方法。

如果你想要多态行为,你需要有兼容的签名。否则编译器不能保证,所需的方法将以多态方式找到。

没有可行的方法来处理签名void Func1()string Func1(int a, int b)多态性。您可以使用内部传递 lambda 的参数来概括它们out,但无论如何 - 要利用多态行为,您需要将它们带到一个共同的签名中。

于 2013-01-07T18:18:45.830 回答
3

方法覆盖意味着修改继承成员的虚拟实现,而不是它的签名。正如您所指出的,该new关键字将隐藏基类对同名成员的实现。然而它只是可选的,看看
在派生类成员中使用新关键字的好处与基类成员同名

于 2013-01-07T18:19:39.037 回答
3

看起来您想要实现类似于对不同类型(如和)ToString具有许多不同风格的方法的行为。.ToString()float.ToString("c")

在这种情况下,不同的实现ToString不是Object.ToString基于参数适当解析的派生对象上的正常附加方法的实现。所有派生类最终都有一个虚拟ToString方法(来自基类并可能在当前类中实现)和可选的其他类似命名的非虚拟方法。

请注意,在 C# 结果类型中,在函数解析时间中考虑了更新,因此您不能真正拥有 2 个具有相同名称和相同参数的函数,并期望“正确”选择一个。如果两者同时可见,则会出现编译时错误。new方法前面的关键字仅使该方法对该类(和派生类)可见,并隐藏具有相同签名的基类方法。不幸的是,当一个人使用基类的变量持有派生类来调用这个方法时,这样做几乎保证了很多混乱——尽管所有努力都隐藏了一个来自基类的虚拟变量,但仍将被调用。

于 2013-01-07T18:26:50.030 回答
1

想一想……它将如何工作?假设您有一个静态类型为A但动态类型为的引用B,如下所示:

foo(B b) { bar(b); }
bar(A a) { 
}

覆盖背后的想法是您在 super/base 上调用一个方法,它会解析为覆盖的实现。按照这种逻辑,您应该能够 inbar调用a.Func1()并且它应该调用 in 的方法B

a.Func1(???)

但这在这里是不可能的,因为缺少参数。

有参数逆变和返回类型协方差的概念;是 SO 中的一个有趣的答案,带有指向 Eric Lippert 的帖子的链接,应该是一个有趣的阅读。

于 2013-01-07T18:35:24.003 回答