views:

988

answers:

8

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#).

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):

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.

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!

+1  A: 
public class SadObject: MoodyObject
    {
        override String getMood()
James Curran
That gets me this error when I try running it: "virtual or abstract members cannot be private". I also made the getMood base virtual and same error.
GregD
This means that your GetMood method is private and not protected as you wrote in your question.
Luc Touraille
It's not though. It's protected. I swear :)
GregD
+2  A: 

By making your method GetMood virtual in Moody and override in 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 :

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.).

Luc Touraille
I've tried that. It only gets me this error when I try to run it "Error 1 'ConsoleApplication1.HappyObject.getMood()': cannot override inherited member 'MoodyObject.getMood()' because it is not marked virtual, abstract, or override"
GregD
Are you absolutely sure you marked your base method as virtual ? I just tried the code and it worked perfectly fine.
Luc Touraille
Here it is cut/pasted for you:using System;public class MoodyObject{ protected virtual String getMood() { return "moody"; } public void queryMood() { Console.WriteLine("I feel " + getMood() + " today!"); }}
GregD
Is my mistake that these all exist in completely different .cs files?
GregD
Nope, it's perfectly correct to define your classes in separate .cs file. Have you tried copy/pasting the code above in your IDE to see if you still have the error?
Luc Touraille
Your code does work. My only issue is that it's the same exact code that I have in separate .cs files. WTF? I've been hacking at this for a couple of hours
GregD
Are all your classes in the same namespace (or all in the global namespace), even though I doubt it would give you the error you have?
Luc Touraille
Maybe you should edit your question, or even write a new one that describes this particular problem (which is a little different from the one presented in your original question).
Luc Touraille
What would you recommend as a better title?
GregD
A: 

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.

Kevin Tighe
+3  A: 

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()....

Dan C.
+12  A: 

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

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).

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() {...}
Ilya Ryzhenkov
+2  A: 

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

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

public class SadObject: MoodyObject    
{        
    override String getMood()
Jeremiah
+2  A: 

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:

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.

My program.cs is this:

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.");
        }
    }
}
Treb
That's exactly how I have it written
GregD
+5  A: 

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

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:

  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.

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.

JoshBerke
What if my baseline is that I'm always moody? So with your design, I'd have three child classes moody, happy, and sad?
GregD
Yes I think your right on you should have a Mood base class with a child class for each Mood you want to model. If Moody is meant to be a mood then it shouldn't be a base class in my opinion.
JoshBerke