我想声明一个父变量,然后为它分配一个子对象 当父变量调用一个方法(同时存在于父/子)时,它应该使用子版本。
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);
}
}
答案 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
修饰符明确标记它。