0

查看以下(伪)模式:

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() 时,我不能在基类中拥有任何功能。我希望派生类提供它自己的字符串表示形式,但仍然希望有一个字符串表示形式告诉我,在这种情况下,它是什么类型的动物。

4

2 回答 2

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

于 2013-07-27T14:04:57.293 回答
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。

于 2013-07-28T01:53:52.540 回答