Я не понимаю, почему неправильно проверять возможные интерфейсы в базовом классе - PullRequest
0 голосов
/ 15 февраля 2019

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

Существует как минимум 2 свойства (назовем их Purpose и Description, обе строки), которые будутбыть добавленным ко многим (но не ко всем) конкретным производным классам, поэтому я создал интерфейсы (IPurposeful и IDescribable) для добавления их при необходимости.Пока все хорошо.

Мне нужен единственный метод, который я могу вызывать для всех классов, производных от моего базового класса, который будет проверять и обновлять свойство Description, если оно действительно IDescribable, или просто возвращать true, если оно есть.не может быть описанЯ хотел бы, чтобы другой подобный метод проверял / обновлял свойство Purpose.

Я добился этого с помощью метода в базовом классе, который выглядит примерно так:

protected bool CheckDescription(bool modify = false)
{
    if (this is IDescribable ele)
    {
        var newDesc = GetCorrectDescription();

        UpdateDescription(newDesc, ele.Description, modify);

        return newDesc.Equals(ele.Description);
    }
    else
    {
        return true;
    }
}

SonarQube помечает "это IDescribable "проверка как блокировщик (плохая практика), и мне интересно, почему?Единственный другой способ репликации этой функциональности, который я могу придумать, - это изменить базовый метод следующим образом:

protected virtual bool CheckDescription(bool modify = false)
{
    return true;
}

, а затем добавить точно такой же метод к потенциально сотням производных классов:

protected override bool CheckDescription(bool modify = false)
{
    var newDesc = GetCorrectDescription();

    UpdateDescription(newDesc, Description, modify);

    return newDesc.Equals(Description);
}

Теперь это может показаться плохой практикой.

РЕДАКТИРОВАТЬ: Изменен шаблон is / as для удаления избыточности

Ответы [ 2 ]

0 голосов
/ 21 марта 2019

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

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

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

0 голосов
/ 15 февраля 2019

Если ваш класс может быть IDescribable, а может быть IPurposeful, тогда дайте ему разумные реализации по умолчанию тех интерфейсов, которые могут бытьops и позволяет вашим классам-потомкам переопределять эти реализации по мере необходимости.

Проверка типов не требуется.Просто вызовите переопределяемые методы и следуйте их результатам.

Если ваши «необязательные» интерфейсы не допускают разумных реализаций no-op, повторно посетите их определения.

Теперь ваш базовый класс можетполагаться на интерфейсы, а не тестировать их.


Здесь вы можете ввести ошибки времени выполнения - но то же самое можно сказать и о методах базового класса, которые требуют реализации определенного интерфейса, который не компилируетсявремя проверки.

...