好的,在我学习的时候,请跟我们男孩和女孩们一起.这是我的问题.
我无法弄清楚为什么我不能从父类重写方法.这是来自基类的代码(是的,我从OOP书中窃取了java代码,并试图用C#重写它).
using System; public class MoodyObject { protected String getMood() { return "moody"; } public void queryMood() { Console.WriteLine("I feel " + getMood() + " today!"); } }
这是继承基类(MoodyObject)的其他2个对象:
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"); } } }
和:
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."); } } }
这是我的主要内容:
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(); } } }
正如你所看到的,非常基本的东西,但这是输出:
今天喜怒无常的物体感觉如何?我今天心情郁闷!
今天伤心的物体感觉如何?我今天心情郁闷!华...号泣
幸福的对象今天感觉如何?我今天心情郁闷!hehehehehehe.按任意键继续 ...
不像我预期的那样.我试图使基本方法虚拟并在尝试覆盖它时调用覆盖,这只是让我得到这个错误"无法覆盖继承的成员'MoodyObject.getMood()',因为它没有标记为虚拟,抽象或覆盖".我也尝试了没有虚拟和覆盖,它认为我试图隐藏基本方法.再说一遍,我是OOP的新手,并会感谢任何指导.
编辑添加:我找到了!MoodyObject.cs只是解决方案资源管理器中的"解决方案项",而不是"ConsoleApplication1"项.我把它拖到解决方案资源管理器所属的位置,瞧!它现在有效.我在下面将Luc的答案标记为答案,因为他提供了我所需要的帮助,以便我解决问题......我在这里学到了很多东西.这太棒了,你们和女孩们都很聪明!
在C#中,默认情况下方法不是虚拟的,因此如果将某个方法设计为可覆盖,则应将其指定为虚拟方法:
class Base { protected virtual string GetMood() {...} }
其次,您必须指定要在派生类中重写基类中的方法.
class Derived : Base { protected override string GetMood() {...} }
如果你没有指定"override"关键字,你将获得隐藏基类型的方法(以及编译器的警告,为方法显示"new"关键字以明确说明).
如果要停止继承链并禁止进一步覆盖该方法,则应将方法标记为已密封,如下所示:
protected sealed override string GetMood() {...}
您需要使用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"; } }
我在这里推荐的是,你有意将MoodyObject作为一个抽象类.(如果你这样做,你必须改变你的主要方法但是你应该去探索它)在喜怒无常的模式中真的有意义吗?我们上面的问题是你的HappyObject不需要为getMood提供一个实现.通过使一个类抽象,它做了几件事:
你不能新建一个抽象类的实例.你必须使用子类.
您可以强制派生子项实现某些方法.
所以要做到这一点你最终:
public abstract class MoodyObject { protected abstract String getMood(); public void queryMood() { Console.WriteLine("I feel " + getMood() + " today!"); } }
请注意您不再为getMood提供实现.
据我所知,在Java中,默认情况下所有方法都是虚拟的.这不是C#的情况,因此您需要使用"虚拟"标记基类方法,例如protected virtual string getMood() ...
,使用"覆盖"覆盖,例如protected override string getMood()...
.