#c# #oop #inheritance #polymorphism
#c# #ооп #наследование #полиморфизм
Вопрос:
У меня есть вопрос, касающийся хранения общего кода в базовом классе и вызова его производным классом, даже если метод триггера производного класса был отправлен из базового. Итак, базовый-> производный-> стек вызовов базового типа.
Следующее выглядит нормально, или это пахнет? Я пронумеровал этапы потока…
public abstract class LayerSuperType
{
public void DoSomething() // 1) Initial call from client
{
ImplementThis(); // 2) Polymorphic dispatch
}
protected abstract void ImplementThis();
protected void SomeCommonMethodToSaveOnDuplication(string key) // 4)
{
Configuration config = GetConfiguration(key);
}
}
public class DerivedOne : LayerSuperType
{
protected virtual void ImplementThis() // 2)
{
SomeCommonMethodToSaveOnDuplication("whatever"); // 3) Call method in base
}
}
public class DerivedTwo : LayerSuperType
{
protected virtual void ImplementThis() // 2)
{
SomeCommonMethodToSaveOnDuplication("something else"); // 3) Call method in base
}
}
Комментарии:
Ответ №1:
Это выглядит абсолютно нормально. Идеальный пример того, почему вы должны использовать абстрактный класс поверх интерфейса. Это немного похоже на шаблон стратегии, и я использовал это довольно регулярно и успешно.
Убедитесь, что то, что делает класс, все еще имеет дело с одной «проблемой», хотя выполняет только одну задачу. Если ваш базовый класс имеет доступ к репозиторию, но объекты представляют документы, не помещайте функциональность в базовый класс, используйте отдельный шаблон / объект репозитория.
Ответ №2:
Выглядит как очень упрощенный шаблонный метод Pattern, в котором ваши подклассы выполняют некоторые специфические действия в нужные моменты реализации вашего алгоритма, но общий поток направляется методом базового класса. Вы также предоставили некоторые услуги своим подклассам в виде методов базового класса; это тоже нормально, если вы хорошо разбираетесь в SOLID.
Ответ №3:
Почему бы и нет, public abstract void DoSomething()
и вообще забыть о ImplementThis()
?
Единственная причина, которую я вижу, чтобы уйти ImplementThis()
, заключается в том, что вы хотите поддерживать согласованный интерфейс, с DoSomething()
которым позже в будущем будет изменяться подпись ImplementThis()
без существенного изменения для вызывающих.
Я согласен, что вы должны придерживаться единой концепции ответственности класса, но с общей точки зрения ООП это выглядит нормально для меня. Я делал подобное много раз.
Ответ №4:
Действительно, немного попахивает тем, что SomeCommonMethodToSaveOnDuplication
вызывается двумя разными способами. Кажется, что это делает две несвязанные вещи. Почему бы не использовать два метода?
Комментарии:
1. Мой пример немного слабоват… Я обновил тело SomeCommonMethodToSaveOnDuplication…
2. Я не замечаю там никаких изменений, так что, полагаю, это означает, что для меня это все еще пахнет.
3. Ну, это не делает две разные вещи. Это вызов базового метода для получения конфигурации для двух элементов. Реализация выборки конфигурации будет отличаться только искомым ключом.
4. Да, новая версия конфигурации действительно устраняет запах.