Каков наилучший способ реализовать свойство Must Set для базового класса? - PullRequest
1 голос
/ 21 июля 2011

У меня есть простой базовый вопрос о C # и наследовании.

В приведенном ниже примере я показываю 2 способа установки обязательных свойств (CaptionDisplayText и Firstname):

public abstract class BaseClass
{
    private string _firstName;

    protected BaseClass(string captionDisplayText)
    {
        this.CaptionDisplayText = captionDisplayText;

        this._firstName = this.GetFirstName();
    }

    protected string CaptionDisplayText { get; private set; }

    protected abstract string GetFirstName();
}

public class DerivedClass : BaseClass
{
   protected DerivedClass():base(String.Empty)
   {

   }

   protected override string GetFirstName()
   {
       return String.Empty;
   }
}

Подход 1, CaptionDisplayText, вводит свойство и устанавливает его в конструкторе, тогда как подход 2 вводит абстрактный метод, который переопределяется в классе Derived.

Я знаю, что подход 2 плох, если метод был виртуальным, а не абстрактным, но здесь он абстрактный, что означает, что он выполняется перед конструктором базового класса, и это будет хорошо.

У меня есть 10-15 свойств / полей, которые должны быть установлены моими производными классами, поэтому я думаю, какой подход будет более понятным, читаемым и тестируемым.

Я думаю, что подход 1 более тестируем, в то время как подход 2 гораздо более читабелен. Подход 2 также будет тестируемым, поскольку фиктивный объект все равно должен будет реализовывать абстрактные элементы.

Какой способ, по вашему мнению, лучше всего, и существует ли третий путь?

Большое спасибо,

Ответы [ 4 ]

0 голосов
/ 21 июля 2011

Для меня это выглядит сбивающим с толку.Почему вы используете GetFirstName, чтобы установить имя.Не лучше ли сделать это в качестве абстрактного метода SetFirstName и использовать там логику вместо того, чтобы скрывать это в конструкторе?Я согласен, что это хитрый / хороший способ сделать это, но может сбить с толку некоторых людей.В производном классе при реализации метода GetFirstName не интуитивно понятно, что вы собираетесь установить это в базовом классе.

что-то вроде защищенной абстрактной строки SetFirstName ();Таким образом, производные классы всегда должны переопределять этот метод, и вы задаете в нем имя.Конечно, вы должны сделать свойство namename защищенным.

Это не обязательный подход.Но, по крайней мере, дает вам подсказку.Или, возможно, просто измените GetFirstName на SetFirstName;)

0 голосов
/ 21 июля 2011

Выполнение логики в конструкторе - это не тот путь, если вы хотите сделать класс тестируемым.Таким образом, делая это ._firstName = this.GetFirstName ();введет дополнительные усилия тестирования, код вызывается, даже если вы не хотите ничего делать с именем.При первом подходе вы могли бы заполнить его нулем, что указывает на то, что это не важно для вашего теста.

0 голосов
/ 21 июля 2011

По моему мнению, лучшим является 1-й, потому что он явно устанавливает данные и предоставляет вызывающей стороне информацию, которая должна быть обязательной, только во время строительства объекта.

Единственная «проблема», которую выЗдесь можно встретить множество свойств, на данный момент похожих на параметры в ctor, что достаточно странно, чтобы увидеть 15 параметров в одном методе.Но может быть этого можно избежать (трудно узнать, не зная вашего приложения), путем перегрузки ctor, если вы из некоторых установленных значений свойств можете вычесть значение других свойств по умолчанию.

Существует словарь / HashSet или любое другое решение, но для меня это решение тоже странное.

Надеюсь, это поможет.

С уважением.

0 голосов
/ 21 июля 2011

Задумывались ли вы об использовании CodeContracts и ClassInvariant?

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