C#中的覆盖和继承

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/337598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 23:45:57  来源:igfitidea点击:

Overriding and Inheritance in C#

c#inheritanceoverriding

提问by GregD

Ok, bear with me guys and girls as I'm learning. Here's my question.

好吧,在我学习的过程中,请多多包涵。这是我的问题。

I can't figure out why I can't override a method from a parent class. Here's the code from the base class (yes, I pilfered the java code from an OOP book and am trying to rewrite it in C#).

我不明白为什么我不能覆盖父类的方法。这是来自基类的代码(是的,我从一本 OOP 书中窃取了 java 代码,并试图用 C# 重写它)。

using System;

public class MoodyObject
{
    protected String getMood()
    {
        return "moody";
    }

    public void queryMood()
    {
        Console.WriteLine("I feel " + getMood() + " today!");
    }
}

and here are my other 2 objects that inherit the base class (MoodyObject):

这是我的其他 2 个继承基类 (MoodyObject) 的对象:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public class SadObject: MoodyObject
    {
        protected String getMood()
        {
            return "sad";
        }

        //specialization
        public void cry()
        {
            Console.WriteLine("wah...boohoo");
        }
    }
}

And:

和:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public class HappyObject: MoodyObject
    {
        protected String getMood()
        {
            return "happy";
        }

        public void laugh()
        {
            Console.WriteLine("hehehehehehe.");
        }
    }
}

and here is my main:

这是我的主要内容:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MoodyObject moodyObject = new MoodyObject();
            SadObject sadObject = new SadObject();
            HappyObject happyObject = new HappyObject();

            Console.WriteLine("How does the moody object feel today?");
            moodyObject.queryMood();
            Console.WriteLine("");
            Console.WriteLine("How does the sad object feel today?");
            sadObject.queryMood();
            sadObject.cry();
            Console.WriteLine("");
            Console.WriteLine("How does the happy object feel today?");
            happyObject.queryMood();
            happyObject.laugh();
        }
    }
}

As you can see, pretty basic stuff, but here's the output:

如您所见,非常基本的东西,但这是输出:

How does the moody object feel today? I feel moody today!

How does the sad object feel today? I feel moody today! wah...boohoo

How does the happy object feel today? I feel moody today! hehehehehehe. Press any key to continue . . .

喜怒无常的对象今天感觉如何?我今天心情不好!

悲伤的对象今天感觉如何?我今天心情不好!哇...嘘

快乐的对象今天感觉如何?我今天心情不好!呵呵呵呵呵呵。按任意键继续 。. .

Not as I expected. I've tried to make the base method virtual and calling override when trying to override it and that just gets me this error "cannot override inherited member 'MoodyObject.getMood()' because it is not marked virtual, abstract, or override". I also tried it without the virtual and override and it thinks I'm trying to hide the base method. Again, I'm new to OOP and would appreciate any guidance.

不像我预期的那样。我试图使基本方法虚拟并在尝试覆盖它时调用覆盖,这只会让我出现这个错误“无法覆盖继承的成员 'MoodyObject.getMood()' 因为它没有标记为虚拟、抽象或覆盖”。我也试过没有 virtual 和 override ,它认为我试图隐藏基本方法。同样,我是 OOP 的新手,希望得到任何指导。

EDITED TO ADD: I found it! The MoodyObject.cs was only a "solution item" in the solution explorer as opposed to a "ConsoleApplication1" item. I dragged it down to where it belonged in the solution explorer and voila! It works now. I marked Luc's answer below as the answer because he offered the help I needed to get to where I have it resolved... I'm learning so much here. It's amazing and you guys and girls are crazy smart!

编辑添加:我找到了!MoodyObject.cs 只是解决方案资源管理器中的一个“解决方案项目”,而不是“ConsoleApplication1”项目。我把它拖到它在解决方案资源管理器中的位置,瞧!它现在有效。我在下面将 Luc 的答案标记为答案,因为他提供了我需要的帮助以解决问题......我在这里学到了很多东西。太神奇了,你们这些家伙和女孩都非常聪明!

采纳答案by Ilya Ryzhenkov

In C# methods are not virtual by default, so if you design some method as overridable, you should specify it as virtual:

在 C# 中,默认情况下方法不是虚拟的,因此如果您将某些方法设计为可覆盖的,则应将其指定为虚拟:

class Base 
{
  protected virtual string GetMood() {...}
}

Second, you have to specify that you are going to override method from base class in derived class.

其次,您必须指定要从派生类中的基类覆盖方法。

class Derived : Base
{
  protected override string GetMood() {...}
}

If you don't specify "override" keyword, you will get method that hides base type (and warning from compiler to put "new" keyword for the method to explicitly state so).

如果您不指定“override”关键字,您将获得隐藏基本类型的方法(并警告编译器为该方法放置“new”关键字以明确说明)。

If you want to stop inheritance chain and disallow further overrides of the method, you should mark method as sealed, like this:

如果要停止继承链并禁止进一步覆盖该方法,则应将方法标记为已密封,如下所示:

  protected sealed override string GetMood() {...}

回答by James Curran

public class SadObject: MoodyObject
    {
        override String getMood()

回答by Luc Touraille

By making your method GetMood virtualin Moody and overridein the derived classes, your code should work. Are you sure you placed these keywords where they belong ? Here is the complete code, that compiles and run just fine :

通过virtual在 Moody 和override派生类中使用GetMood 方法,您的代码应该可以工作。您确定将这些关键字放在它们所属的位置吗?这是完整的代码,编译并运行得很好:

public class MoodyObject
{
    protected virtual String getMood()
    {
        return "moody";
    }

    public void queryMood()
    {
        Console.WriteLine("I feel " + getMood() + " today!");
    }
}

public class SadObject : MoodyObject
{
    protected override String getMood()
    {
        return "sad";
    }

    //specialization
    public void cry()
    {
        Console.WriteLine("wah...boohoo");
    }
}

public class HappyObject : MoodyObject
{
    protected override String getMood()
    {
        return "happy";
    }

    public void laugh()
    {
        Console.WriteLine("hehehehehehe.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        MoodyObject moodyObject = new MoodyObject();
        SadObject sadObject = new SadObject();
        HappyObject happyObject = new HappyObject();

        Console.WriteLine("How does the moody object feel today?");
        moodyObject.queryMood();
        Console.WriteLine("");
        Console.WriteLine("How does the sad object feel today?");
        sadObject.queryMood();
        sadObject.cry();
        Console.WriteLine("");
        Console.WriteLine("How does the happy object feel today?");
        happyObject.queryMood();
        happyObject.laugh();

        Console.Read();
    }
}

Maybe your mistake comes from the fact that in Java, all methods are virtual, which is not the case is C# (as pointed out by Dan C.).

也许你的错误来自这样一个事实,即在 Java 中,所有方法都是虚拟的,而 C# 并非如此(正如 Dan C. 所指出的)。

回答by Kevin Tighe

You need to mark the overrides of getMood with the "override" keyword. You'll also need to mark the base getMood method with the "virtual" keyword.

您需要使用“override”关键字标记 getMood 的覆盖。您还需要使用“virtual”关键字标记基本的 getMood 方法。

回答by Dan C.

As far as I know, in Java all methods are virtual by default. This is not the case with C#, so you need to mark the base class methods with "virtual", e.g. protected virtual string getMood() ...and the overrides with "override", e.g. protected override string getMood()....

据我所知,在 Java 中,默认情况下所有方法都是虚拟的。这不是 C# 的情况,所以你需要用“虚拟”标记基类方法,例如protected virtual string getMood() ...,用“覆盖”标记覆盖,例如protected override string getMood()...

回答by Jeremiah

You need to tell C# that your object is overriding the function from the base class.

您需要告诉 C# 您的对象正在覆盖基类中的函数。

Here is the MSDN article about the syntax you need: http://msdn.microsoft.com/en-us/library/ebca9ah3(VS.71).aspx

这是关于您需要的语法的 MSDN 文章:http: //msdn.microsoft.com/en-us/library/ebca9ah3(VS.71).aspx

public class SadObject: MoodyObject    
{        
    override String getMood()

回答by Treb

If you want to override a base class method, it needs to be declared as virtual. The overriding method in a derived class has to be explicitly declared as override. This should work:

如果要覆盖基类方法,则需要将其声明为virtual. 派生类中的覆盖方法必须显式声明为override. 这应该有效:

public class BaseObject
{
    protected virtual String getMood()
    {
        return "Base mood";
    }

    //...
}

public class DerivedObject: BaseObject
{
    protected override String getMood()
    {
        return "Derived mood";
    }
    //...
}

Edit:I just tried it in a c# console application, and it compiles. So the source code you use should differ in some tiny but important piece from what you posted here.

编辑:我刚刚在 ac# 控制台应用程序中尝试过,它可以编译。因此,您使用的源代码应该与您在此处发布的内容在一些微小但重要的部分有所不同。

My program.cs is this:

我的 program.cs 是这样的:

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {    
            // leaving out your implementation to save space...    
        }
    }    

    public class SadObject : MoodyObject
    {
        protected override String getMood()
        {
            return "sad";
        }

        //specialization
        public void cry()
        {
            Console.WriteLine("wah...boohoo");
        }
    }

    public class HappyObject : MoodyObject
    {
        protected override String getMood()
        {
            return "happy";
        }

        public void laugh()
        {
            Console.WriteLine("hehehehehehe.");
        }
    }
}

回答by JoshBerke

You need to use the override keyword to override any virtual or implement any abstract methods.

您需要使用 override 关键字来覆盖任何虚拟或实现任何抽象方法。

public class MoodyObject
{
    protected virtual String getMood() 
    { 
        return "moody"; 
    }    
    public void queryMood() 
    { 
        Console.WriteLine("I feel " + getMood() + " today!"); 
    }
}

public class HappyObject : MoodyObject
{
    protected override string getMood()
    {
        return "happy";
    }
}

What I would recommend here is that you probally meant for MoodyObject to be an abstract class. (You'd have to change your main method if you do this but you should explore it) Does it really make sense to be in a moody mode? The problem with what we have above is that your HappyObject is not required to provide an implementation for getMood.By making a class abstract it does several things:

我在这里建议的是,您可能打算让 MoodyObject 成为一个抽象类。(如果你这样做,你必须改变你的主要方法,但你应该探索它)处于喜怒无常的模式真的有意义吗?我们上面的问题是你的 HappyObject 不需要提供 getMood 的实现。通过使类抽象它可以做几件事:

  1. You cannot new up an instance of an abstract class. You have to use a child class.
  2. You can force derived children to implement certain methods.
  1. 你不能新建一个抽象类的实例。您必须使用子类。
  2. 您可以强制派生子级实现某些方法。

So to do this you end up:

所以要做到这一点,你最终会:

public abstract class MoodyObject
{
    protected abstract String getMood();

    public void queryMood() 
    { 
        Console.WriteLine("I feel " + getMood() + " today!"); 
    }
}

Note how you no longer provide an implementation for getMood.

请注意您如何不再提供 getMood 的实现。