Поведенческий полиморфизм подтипов

250
09 мая 2018, 04:14

Цитата из википедии: Наследование, — даже в языках программирования, которые поддерживают применение наследования как механизма, обеспечивающего полиморфизм подтипов, — не гарантирует поведенческий полиморфизм подтипов; смотри: «Принцип подстановки» Барбары Лисков.

Что же здесь подразумевают под поведенческим полиморфизмом подтипов? Как грамотно и лаконично ответить на этот вопрос?

Я же понимаю это так: Опять же цитата из википедии: Более простыми словами можно сказать, что поведение наследуемых классов не должно противоречить поведению, заданному базовым классом, то есть поведение наследуемых классов должно быть ожидаемым для кода, использующего переменную базового типа. Из этого следует, что наследование не защищает программиста, от того, что он может изменить поведение в переопределенном методе. Например метод add() в базовом классе добавляет объект, а его можно легко переопределить и этот метод станет удалять некий объект. Сохранение поведения базового метода и есть поведенческий полиморфизм.

Прав ли я?

Answer 1

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

class Rechtangle {
    protected int width;
    protected int height;
    public void setWidth(int w) {
        this.width = w;
    }
    public void setHeight(int h) {
        this.height = h;
    }
    public int area() {
        return width * height;
    }
}

И мы добавляем новый класс "Квадрат", чем он отличается от прямоугольника, тем что его стороны должны изменяться одновременно, если мы меняем высоту, то и должна меняться ширина, пример

class Square extends Rechtangle {
    @Override
    public void setWidth(int w) {
       this.width = w;
       this.height = w;
    }
    @Override
    public void setHeight(int h) {
       this.width = h;
       this.height = h;
    }
}

А теперь представьте, что какой-то программист написал следующий код

void mainProcedure(Rechtangle figure) {
    figure.setWidth(5);
    figure.setHeight(3);
    assert figure.area() == 15; 
}

Давайте теперь вызовем эту функцию с реализацией квадрата

mainProcedure(new Square())

Будет выброшено AssertionError, вот вам наглядное нарушение принципа LSP и поведенческого полиморфизма. Потому что фактически квадрат это не прямоугольник и разработчик процедуры mainProcedure не ожидал что он может получить квадрат маскирующийся за прямоугольником. Программист который написал процедуру прав. Он проверил контракт который должен был соблюдаться прямоугольником, но был нарушен квадратом.

READ ALSO
мин элемент под диагональю [требует правки]

мин элемент под диагональю [требует правки]

Дано матрицу А [m] [m]Найдите минимальный из элементов, расположенных под главной диагональю

273
Использование cuda::CascadeClassifer в OpenCv

Использование cuda::CascadeClassifer в OpenCv

Возникла проблема с использованием в opencv cuda::CascadeClassifer

249
Не работает чтение входного потока QProcess

Не работает чтение входного потока QProcess

Предположим, есть программа, которая во время выполнения пишет лог в стандартный поток вывода, например такая:

235
Нарисовать дугу в QGraphicsItem

Нарисовать дугу в QGraphicsItem

Есть класс class Edge : public QGraphicsItem, в котором реализовано рисование стрелок от одной вершины (Node) до другой (скрин ниже)Теперь необходимо добавить...

223