为什么在初始化子对象并将其分配给父对象时调用父方法

时间:2014-09-26 21:12:33

标签: c# methods override parent

我想声明一个父变量,然后为它分配一个子对象 当父变量调用一个方法(同时存在于父/子)时,它应该使用子版本。

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);
    }
}

1 个答案:

答案 0 :(得分:2)

您的代码存在的问题是您没有在基类中将getAnswer方法标记为虚拟。

所以,在你隐藏的TwoIntDivision类中 - 不要覆盖(扩展)基类方法:

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

然后,当您转换对象时,根据类型,它将使用您正在使用的类型的方法。这是完全预期的行为,可以在正确的背景下派上用场。

要获得您期望的行为,请按以下方式修改您的定义:

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"

作为旁注,如果您来自Java背景,则默认情况下C#方法是final(非虚拟)。如果要允许方法在派生类中可重写,则必须使用virtual修饰符明确标记它。