Search code examples
c#methodsoverridingparent

Why parent method is called when child object is initialized and assigned to a parent object


I want to declare a parent variable, then assign it with a child object when the parent variable calls a method (exists in both parent / child), it should use the child's version.

public abstract class TowInt
{
    public int One;
    public int Two;
    public char Operator;
    public int Result;
    public int Remainder;

    public void init()
    {
        calc();
    }

    protected abstract void calc();

    public string getAnswer()
    {
        return Convert.ToString(Result);
    }
    public string getQuestion()
    {
        return string.Format("{0} {1} {2} = ", One, Operator, Two);
    }
}

public class TwoIntPlus : TowInt
{

    public TwoIntPlus(int one, int two)
    {
        One = one;
        Two = two;
        Operator = '+';
    }
    protected override void calc()
    {
        Result = One + Two;
    }
}

public class TwoIntDivision : TowInt
{
    public TwoIntDivision(int one, int two)
    {
        One = one;
        Two = two;
        Operator = '/';
    }
    protected override void calc()
    {
        Result = One / Two;
        Remainder = One % Two;
    }

    new public virtual string getAnswer()
    {
        return string.Format("{0}R{1}", Result, Remainder);
    }
}



using System.IO;

class ConsoleApplication1
{
    static void Main()
    {
        // For child class, the child method getAnswer() is called
        TwoIntDivision n2 = new TwoIntDivision(32, 4);
        n2.init();
        Console.WriteLine(n2.getQuestion() + n2.getAnswer());
        // 32 / 4 = 8R0  -- this is what I expected

        // If assign a child object to parent, then the parent method is called
        TowInt two;
        two = new TwoIntDivision(32, 4);
        two.init();
        Console.WriteLine(two.getQuestion() + two.getAnswer());
        // 32 /4 = 8 -- this is not what I expected

        two = new TwoIntPlus(32, 4);
        two.init();
        Console.WriteLine(two.getQuestion() + two.getAnswer());



        Thread.Sleep(5000);
    }
}

Solution

  • The problem with your code is that you have not marked the getAnswer method as virtual in the base class.

    So, in the TwoIntDivision class you are hiding - not overriding (extending) the base class method:

    // this is hiding the base class method, not overriding it (notice the new modifier)
    new public virtual string getAnswer()
    

    Then, when you cast your object, depending on the type it will use the method for the type you are working with. This is totally expected behavior and can come in handy in the right context.

    To get the behavior you expect, modify your definitions like this:

    public abstract class TowInt
    {    
       public virtual string getAnswer() {
           return "Hello from Base-Class";
      }    
    }
    
    public class TwoIntDivision : TowInt
    {
       public override string getAnswer() {
            return "Hello from Division";
       }
    }
    
    TowInt t = new TwoIntDivision();
    Console.WriteLine(t.getAnswer());     // prints "Hello from Division"
    

    As a side note, in case you are coming from a Java background, in C# methods are final (non-virtual) by default. If you want to allow a method to be overrideable in a derived class you have to explicitly mark it with the virtual modifier.