2013-07-27 2 views
0

Посмотрите на следующий (псевдо) модель:Рекурсивный абстрактный ToString() в базовом классе?

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 

Проблема: когда я хочу f orce ToString() в производном классе, я не могу иметь никаких функциональных возможностей в базовом классе. Я хочу, чтобы производный класс предоставлял собственное строковое представление самого себя, но все же хочу иметь строковое представление, которое говорит мне, в этом случае, какое это животное.

+1

Что именно вы хотите достичь? –

+1

'public abstract override string ToString()' ????????????? OMG, это превосходит все мои ожидания :-) –

+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.

+0

Благодарим вас, я буду придерживаться вашего предложения, хотя это может сбивать с толку, что метод «ToString()» производного класса дает только строковое представление базового класса, а «GetAttributes()» служит для этой цели. :) – Atrotygma

+0

+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, если есть необходимость.

Смежные вопросы