基类中的递归抽象ToString()?

时间:2013-07-27 13:56:54

标签: c# .net oop polymorphism

查看以下(伪)模式:

public abstract class Animal {

     public abstract AnimalType { get; }

     public abstract override string ToString() {
          return String.Format("{0}={1}", AnimalType, this.ToString());
                                                         ^
                                                // does this even work?
     }

}

会强制从它派生的每个类看起来像这样:

public sealed class Horse : Animal {

     // horse specific declaration
     private string _name;
     private int    _age;

     // forced
     public override AnimalType { 
          get { return AnimalType.Horse; } 
     }

     // horse specific declaration
     public Name {
          get { return _name; }

     public Horse(string name, string age) {
          _name = name;
          _age  = age;
     }

     // forced
     public override string ToString() {
          return String.Format("{0}({1}", _name, _age);
     }

}

会产生以下输出:

Horse =MyHorseName(3);
Tiger =SomeOtherAttributesBecauseTigerIsDifferent

问题是:当我想在派生类中强制使用ToString()时,我不能在基类中使用任何功能。我希望派生类提供它自己的字符串表示形式,但仍希望有一个字符串表示形式告诉我,在这种情况下,它是什么类型的动物。

2 个答案:

答案 0 :(得分:5)

我认为您最好的办法是声明并调用单独的protected abstract string GetAttributes()方法。此外,您可以使用sealed来阻止子类覆盖ToString()实现:

public abstract class Animal {
     public abstract AnimalType { get; }

     public sealed override string ToString() {
          return String.Format("{0}={1}", AnimalType, this.GetAttributes());
     }

    protected abstract string GetAttributes();
}

public sealed class Horse {
    protected override string GetAttributes() {
        return String.Format("{0}({1}", _name, _age);
    }
}

如果Horse此时尝试覆盖ToString,则会收到编译错误。同时,它被迫实施GetAttributes

答案 1 :(得分:0)

我不知道可能会将ToString代码中使用的变量推送到基类的某些默认值,但让子类更改它们。因此基类中的ToString()代码不需要被覆盖,但会提供自定义输出,因为基类变量会不断变化为孩子想要的变化。例如,考虑一下:

  abstract class cbase
  {
    internal string _var1 = "def1", _var2 = "def2";

    public override string ToString()
    {
      return string.Format("{0} - {1}", _var1, _var2);

    }
  }
  class cchild1 : cbase
  {

    public cchild1()
    {
      _var1 = "umm";
      _var2 = "ok";

    }
  }
  class cchild2 : cbase
  {

  }

所以对于上面的代码:

new cchild1().ToString()

将输出

umm - OK

new cchild2().ToString()

将输出:

def1 - def2

所以这样,你不必在每个子类中重写ToString,但是输出格式仍然在你在基类中定义的所有继承类中保持一致。但如果有需要,你也可以自由覆盖ToString。