Atrotygma
Atrotygma

Reputation: 1153

Recursive abstract ToString() in base class?

Look at the following (pseudo) pattern:

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?
     }

}

which would force every class that derives from it look like this:

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

}

which would produce the following output:

Horse =MyHorseName(3);
Tiger =SomeOtherAttributesBecauseTigerIsDifferent

Problem is: When I want to force ToString() in the derived class, I can't have any functionality in the base class. I want the derived class to provide it's own string representation of itself, but still want to have a string representation that tells me, in this case, what type of animal it is.

Upvotes: 0

Views: 2108

Answers (2)

user734028
user734028

Reputation: 1111

I dont know maybe push the variables used in the ToString code up the base class with some default values, but have the child classes change them. So the ToString() code in base class wont need to be overriden but will provide custom outputs as the base class variables keep changing to whatever the child wants them to be. for example consider this:

  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
  {

  }

so for the above code:

new cchild1().ToString()

will output

umm - OK

while

new cchild2().ToString()

will output:

def1 - def2

so in this way, you dont have to override ToString in each child class but still the output format stays consistent in all inherited classes as you have defined in the base class. But you also have the liberty to override the ToString if there is a need.

Upvotes: 0

Chris Sinclair
Chris Sinclair

Reputation: 23218

I think your best bet is to declare and call a separate protected abstract string GetAttributes() method. In addition, you can use sealed to prevent subclasses from overriding the ToString() implementation:

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

If Horse attempted to override ToString at this point, it would receive a compile error. Meanwhile, it's forced to implement GetAttributes.

Upvotes: 5

Related Questions