Правильно ли я понимаю принцип «Открыто-закрыто»?

#c# #inheritance #polymorphism #open-closed-principle

#c# #наследование #полиморфизм #принцип open-closed

Вопрос:

Допустим, в первой версии моего гипотетического программного обеспечения у меня есть простой класс, подобный этому:

 public Class Version1
{
    public void Method1()
    {
       Console.WriteLine("Hello");
    }
}
  

Во второй версии у меня есть обновление, которое требует, чтобы метод 1 был изменен следующим образом:

 public Class Version1
{
    public void Method1()
    {
       Console.WriteLine("Hello");
       Console.WriteLine("World");
    }
}
  

И в третьей версии у меня есть обновление, которое требует добавления другого метода к этому классу, подобного этому:

 public Class Version1
{
    public void Method1()
    {
       Console.WriteLine("Hello");
       Console.WriteLine("World");
    }

    public int Method2()
    {
        return 7;
    }    
}
  

Теперь, насколько я понимаю принцип Open-Closed, в обоих обновлениях я нарушил этот принцип, потому что я изменил класс, который выполнял желаемую работу в первой версии моего программного обеспечения.

Я думаю, что это должно быть сделано так, но не уверен, правильно ли это, вот так:

 public virtual Class Version1
{
    public virtual void Method1()
    {
       Console.WriteLine("Hello");
    }
}

public virtual Class Version2 : Version1
{
    public override void Method1()
    {
       Console.WriteLine("Hello");
       Console.WriteLine("World");
    }
}  

public Class Version3 : Version2
{      
    public int Method2()
    {
        return 7;
    }

}
  

Насколько это неправильно / правильно?

Ответ №1:

Да, оба метода нарушают принцип.

Первый метод изменяет значение Method1 , больше не только показывая Hello . Ваш второй метод расширяет первую версию, которая разрешена, но вам следовало использовать наследование для расширения функциональности.

Существует множество способов добиться «быть закрытым или открытым». Некоторые используют наследование, чтобы разрешить модификации объекта, другие используют интерфейсы. Если бы вы использовали интерфейсы, второй метод также мог бы рассматриваться как нарушение, поскольку это потребовало бы уточнения определения интерфейса.

Комментарии:

1. Добавление метода к исходному классу, на мой взгляд, считается модификацией не только для интерфейсов, как вы говорите

2. Ну, для этого не нужно пересматривать существующий код, зависящий от него, так что это просто расширение, верно?

3. @AlexanderDerck «Но он также открыт, поскольку любой новый класс может использовать его как родительский, добавляя новые функции. Когда класс-потомок определен, нет необходимости изменять исходный или беспокоить его клиентов.»

4. Да, это то, что я имею в виду, если вы наследуете от него и добавляете дополнительный метод, базовый класс не был изменен -> «нет необходимости изменять исходный». Итак, строго говоря, я думаю, что добавление его в базовый класс является нарушением принципа o / c.

5. @AlexanderDerck Извините, вы полностью правы. Обновлено.