code4Better Ответов: 1

Работает ли подстановка Лискова с абстрактным классом?


Is Liskov Substitution works with out abstract class?

For ex:
public class SumCalculator
{
    protected readonly int[] _numbers;
 
    public SumCalculator(int[] numbers)
    {
        _numbers = numbers;
    }
 
    public virtual int Calculate() => _numbers.Sum();
}

public class EvenNumbersSumCalculator: SumCalculator
{
    public EvenNumbersSumCalculator(int[] numbers)
        :base(numbers)
    {
    }
 
    public override int Calculate() => _numbers.Where(x => x % 2 == 0).Sum();
}

When i use following statement, i get expected answer and logic is perfect.

SumCalculator evenSum = new EvenNumbersSumCalculator(numbers);
Console.WriteLine($"The sum of all the even numbers: {evenSum.Calculate()}");

But LSP is not followed here because when child class is substituted, behaviour got  changed.

Then i created an abstarct class 
public abstract class Calculator
{
    protected readonly int[] _numbers;
 
    public Calculator(int[] numbers)
    {
        _numbers = numbers;
    }
 
    public abstract int Calculate();
}
Now my both classes will implement from abstract Calculator class and i got expected result also. 

But my question is when we use just base class and child class, always it will changes behaviour and it will be against LSP. Is this correct? If not can somebody provide me some more details. 

Please dont send me links because i have seen manylinks and could not get answer.


Что я уже пробовал:

For ex:
public class SumCalculator
{
    protected readonly int[] _numbers;
 
    public SumCalculator(int[] numbers)
    {
        _numbers = numbers;
    }
 
    public virtual int Calculate() => _numbers.Sum();
}

public class EvenNumbersSumCalculator: SumCalculator
{
    public EvenNumbersSumCalculator(int[] numbers)
        :base(numbers)
    {
    }
 
    public override int Calculate() => _numbers.Where(x => x % 2 == 0).Sum();
}

1 Ответов

Рейтинг:
10

F-ES Sitecore

Вы можете использовать интерфейс, а не абстрактный класс, однако я не думаю, что LSP говорит, что результат должен быть таким же, просто код не ломается. Если результат двух объектов один и тот же, то нет никакого смысла иметь два из них или менять один на другой.


BillWoodruff

+5

code4Better

Спасибо за ответ @F-ES Sitecore. Принцип замещения Лискова гласит, что "объект производного класса должен быть способен заменить объект базового класса, не внося никаких ошибок в систему или не изменяя поведение базового класса". Когда он говорит без изменения поведения, виртуальное переопределение не может быть использовано без абстрактного или интерфейса. Это означает, что для адаптации LSP класс должен иметь интерфейс или абстракцию в качестве базового класса. Это было мое замешательство.

F-ES Sitecore

Конечно, в некоторых случаях это облегчает работу, если вы используете общий абстрактный класс или интерфейс, но я не думаю, что это строго необходимо. Вы можете иметь базовый класс Animal со свойством "NumberOfLegs" и заменить Animal на Cat, и Ваше свойство NumberOfLegs может продолжать функционировать, даже если вы не используете абстрактные классы или интерфейсы.

code4Better

Да, мы можем. Спасибо!