Я правильно понимаю принцип открытого-закрытого?

Скажем, в первой версии моего гипотетического программного обеспечения у меня есть такой простой класс:

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;
    }

}

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


person Ivan    schedule 24.10.2016    source источник


Ответы (1)


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

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

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

person Patrick Hofman    schedule 24.10.2016
comment
На мой взгляд, добавление метода в исходный класс считается модификацией не только для таких интерфейсов, как вы говорите. - person Alexander Derck; 24.10.2016
comment
Что ж, ему не нужно пересматривать существующий код, зависящий от него, так что это просто расширение, верно? - person Patrick Hofman; 24.10.2016
comment
Да, это та часть, которая также смущает меня больше всего во всей этой истории... потому что то, как люди интерпретируют этот принцип, заключается в том, что класс не должен меняться, но добавление другого метода в класс, на мой взгляд, считается модификацией. - person Ivan; 24.10.2016
comment
@AlexanderDerck Но он также открыт, поскольку любой новый класс может использовать его как родительский, добавляя новые функции. Когда определен класс-потомок, нет необходимости изменять исходный класс или беспокоить его клиентов. - person Patrick Hofman; 24.10.2016
comment
Да, именно это я и имею в виду, если вы наследуете его и добавляете дополнительный метод, то базовый класс не изменился —> нет необходимости менять исходный. Строго говоря, я думаю, что добавление его в базовый класс является нарушением принципа o/c. - person Alexander Derck; 24.10.2016
comment
@AlexanderDerck Извините, вы совершенно правы. Обновлено. - person Patrick Hofman; 24.10.2016