【问题标题】:Why to use override in Inheritance method of c# instead of function为什么在c#的继承方法中使用覆盖而不是函数
【发布时间】:2018-10-22 07:04:12
【问题描述】:

我想知道,虽然继承可以用来继承派生类中的属性和方法。

为什么我们不在派生类中编写函数,而是将它们声明为覆盖。

以下示例将详细解释我的问题。

class Net
{
    public virtual void Act()
    {
    }
}

class Perl : Net
{
    public override void Act()
    {
    Console.WriteLine("Perl.Act");
    }
}

class Python : Net
{
    public override void Act()
    {
    Console.WriteLine("Python.Act");
    }
}
// Use base class and derived types in a List.
List<Net> nets = new List<Net>();
nets.Add(new Perl());
nets.Add(new Python());

// Call virtual method on each instance.
foreach (Net net in nets)
{
    net.Act();
}

在上面的示例中,act 函数可以声明为“新”函数,为什么我们要选择覆盖基函数??

编辑:假设我有一个案例如下

class Net
{
    public virtual void Act()
    {
    }

    public virtual void secondMethod()
    {
    }
}

class Perl 
{
    public override void Act()
    {
        Console.WriteLine("Perl.Act");
    }

    public override void secondMethod()
    {
        Console.WriteLine("Perl.Act");
    }
}

class Python 
{
    public new void Act()
    {
        Console.WriteLine("Python.Act");
    }

    public override void secondMethod()
    {
        Console.WriteLine("Perl.Act");
    }
}

那我该怎么办。 在上述情况下,我希望继承基类,但我正在实现的功能可能不同。 在这种情况下,我应该使用覆盖还是编写完全不同的方法。

【问题讨论】:

  • 不做任何其他更改,将任何子方法声明为new,看看会发生什么。

标签: c# oop inheritance


【解决方案1】:

因为在您的基类中没有 virtual 方法,您将无法使用循环调用 Act

foreach (Net net in nets)
{
    net.Act();
}

foreach 并不是唯一可以使用它的地方。假设您有一个名为Foo 的方法,它以Net 实例为参数:

public static void Foo(Net net)
{
    net.Act();
}

您仍然可以将PythonPerl 都传递给该方法,它们都将执行自己的Act 方法逻辑。

virtual 在您想提供一些基本的默认功能并能够override 派生类中的默认功能的任何地方都很有用。

你应该阅读Knowing When to Use Override and New Keywords (C# Programming Guide)

【讨论】:

  • 是的,我知道这一点。我想知道为什么专门使用 virtual 而不是编写新方法。是不是只能用foreach循环??
【解决方案2】:

new 关键字用于方法隐藏,主要用于版本控制目的,但请注意这两种方法在派生类中仍然可用!并且可以通过简单的cast 访问。但是另一方面,通过方法覆盖,你覆盖了行为(这就是我们所说的多态),所以在派生类中,被覆盖的方法将完全取代基方法,因此无法访问通过派生类的实例,即使向上转型到基类!因为虚方法被覆盖的方法所取代。 让我通过一个示例向您展示这个概念:

public class Base
{
    public virtual void VirtualMethod() { }
    public void NewMethod() { }
}

public class Derived : Base
{
    public override void  VirtualMethod() { }
    public new void NewMethod() { }
}

...

Base derived = new Derived();
derived.VirtualMethod(); // Derived.VirtualMethod()
derived.NewMethod(); // Base.NewMethod()
((Derived)derived).NewMethod(); // Derived.NewMethod()

【讨论】:

  • 感谢 Arin Ghazarian。这就是我一直在寻找的。​​span>
  • 其他答案也很好,我只是试图解释更基本的 OOP 概念。希望这会有所帮助。
  • 我并不是要忽视其他很好且内容丰富的答案,但我正在寻找 ((Derived)derived).NewMethod(); // Derived.NewMethod() 特别是这个语句。
  • 很高兴它对您有所帮助。
【解决方案3】:

在上面的示例中,act 函数可以声明为“新”函数,为什么我们应该选择覆盖基函数

继承旨在使用基类提供的内容以及必要的额外功能。如果您不想使用基类的功能,为什么要首先继承?

【讨论】:

  • 假设我在基类方法 a 和 b 中有 2 个方法我想继承方法 a 并且我想在派生类中编写一个新的 B。在这种情况下,我使用继承,但我应该将两个基本方法都声明为 Virtual 并覆盖它们。或者我应该在派生类中使用关键字 New 编写一个具有相同名称的新方法
  • 如果你不希望你的第二种方法被覆盖,那么它首先不应该是虚拟的。考虑使用接口并将所需的功能分解为单独的接口。除非您提供完整的图片,否则很难正确回答。
猜你喜欢
  • 2016-01-25
  • 1970-01-01
  • 2018-05-09
  • 2011-01-10
  • 1970-01-01
  • 2022-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多