Как реализовать базовый класс с методом и при этом заставить производный класс переопределить его? - PullRequest
5 голосов
/ 25 августа 2009

Имея что-то вроде этого:

public abstract class AAA
{
  protected abstract virtual string ToString()    // Error
  {
    // Base Stuff
  }
}

public abstract class BBB : AAA
{
  public override string ToString()
  {
    // Use base.ToString();
    // More Stuff
  }
}

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

Я знаю, что мог бы сделать что-то подобное (прокрутить вниз), но я искал правильный путь.

public abstract class AAA
{
  public abstract string ToString();
  protected string ToString2()
  {
    // Base Stuff
  }
}

public class BBB : AAA
{
  public override string ToString()
  {
    // Use base.ToString2();
    // More Stuff
  }
}

Я также мог бы, вероятно, создать интерфейс IAAA и построить свой класс BBB, как

public class BBB : AAA, IAAA { ... }

но не смотри на меня правильно.

Ответы [ 3 ]

5 голосов
/ 25 августа 2009

Ваш подход по сути правильный путь ...

Редактировать:

Ваша "спецификация":

  1. Поведение по умолчанию
  2. Обязательное переопределение

Теперь, поскольку вы, похоже, хотите, чтобы «поведение по умолчанию» всегда выполнялось, вам нужно

public string ToString()
{
    // placeholder for some default behaviour

    string result = doToString();

    // placeholder for some more default behaviour

    return result;
}

protected abstract string doToString();

Это работает, только если вы знаете, что делает базовый класс в целом, и хотите предоставить реализацию для doToString() в производном классе. Это известно как шаблонный метод шаблон проектирования.

Однако, если вы ищете способ требовать от разработчика производного класса для вызова base.ToString() в его реализации ToString(), то сделать это невозможно. Разрешая переопределение, вы даете производному классу контроль над его реализацией.

Вы можете задокументировать свою рекомендацию всегда звонить base.ToString(), но это все.

Использование интерфейса определяет публичный контракт для вашего класса. Это не дает вам никакого дополнительного преимущества по сравнению с шаблоном Template Method, так как вам все еще нужно извлечь из базового класса, чтобы получить реализацию по умолчанию.

Есть ли у вас какие-либо подробности о том, что вы пытаетесь предоставить в своем базовом классе как "поведение по умолчанию"? Может быть, это поможет прийти к лучшему решению. Глядя на упомянутый вопрос, это по сути тот же подход.

2 голосов
/ 26 августа 2009

Я только что узнал, что делать, чтобы получить именно то поведение, которое я хотел:

public abstract class AAA
{
  protected abstract string ToStringSpecific();
  protected string ToString()
  {
    // Base Stuff
    ...
    // Use this.ToStringSpecific();
  }
}

public class BBB : AAA
{
  protected override string ToStringSpecific()
  {
    // Specific Stuff
  }
}
0 голосов
/ 25 августа 2009

Нет, невозможно превратить текущую виртуальную функцию в абстрактную функцию. Единственный способ обеспечить это - создать еще одну абстрактную функцию, как вы и предлагали. Возможно, это более подходящий подход (и я бы с этим согласился).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...