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