Нарушает ли перегрузка принцип замены Лискова?

Я новичок в ООП. Недавно я прочитал о принципе подстановки Лискова.

В приведенном ниже коде класс Square наследует Give_Area. Предположим, что класс Square выполняет какие-то действия, связанные с квадратом (например, проверку действительности). Give_Area дает площадь квадрата (4 вершины по периметру круга) и площадь круга. Итак, если мне задан Радиус, я должен распечатать область круга и квадрата (состоит из вершин, расположенных по периметру этого круга). Чтобы получить площадь круга, я использовал параметр. Но нет параметра при получении площади квадрата. Таким образом, я сделал здесь перегрузку.

#include<iostream>
#include<cmath>
using namespace std;

class Give_Area
{
    public:
    double Radius;

    double Area(double pi)
    {
        return pi*Radius*Radius;
    }

    double Area()
    {
        double temp = sqrt(2.0)*Radius;
        return temp*temp;
    }
};

class Square : public Give_Area
{
    public:
    bool Validity()
    {
        //checking validity
    }
};

int main()
{
    Give_Area* area = new Square();
    area->Radius = 3.0;
    cout<< "Area of Circle: " << area->Area(3.14159) <<endl;
    cout<< "Area of Square: " << area->Area() <<endl;
    return 0;
}

У меня вопрос ..

Is this overloading violating Liskov Substitution Principle?

Если этот код нарушает, то не мог бы кто-нибудь дать мне пример перегрузки, которая не нарушит принцип подстановки Лискова?

Я погуглил свой запрос, но ничего не нашел. :(

Заранее спасибо.


person Mukit09    schedule 17.12.2014    source источник
comment
Свойства Shape должны быть инкапсулированы в самой форме как переменные-члены, а не передаваться в качестве аргументов в методы получения области.   -  person Matt Coubrough    schedule 17.12.2014
comment
На самом деле я могу быть здесь в меньшинстве, но я считаю Лисков плохим, поскольку он излишне ограничивает то, что вы можете делать, зная, как все должно работать. См. stackoverflow.com/questions/16804817/. Практический результат, если вы понимаете, как работают ваши классы, нарушения Лискова не имеют значения.   -  person paxdiablo    schedule 17.12.2014
comment
Собственность SHAPE ?? Вы имели в виду ПЛОЩАДЬ? @MattCoubrough   -  person Mukit09    schedule 17.12.2014
comment
Нет, я имею в виду свойства ЛЮБОЙ формы. Вся концепция заключается в том, что вы можете поменять одну форму на другую, вызвать метод с точно такой же подписью и получить действительный результат, не нарушающий ваш код. Например, если у меня есть вектор фигур разных типов, все наследующие от абстрактного базового класса с помощью метода Area(), я должен иметь возможность суммировать общую площадь всех фигур, независимо от того, какие они формы, вызывая Area ( ) на каждой фигуре по очереди и добавляю ее к моей сумме.   -  person Matt Coubrough    schedule 17.12.2014
comment
Можно ли сохранить принцип подстановки Лискова, используя перегрузку? Если возможно, не могли бы вы привести мне пример? Я пробовал, но так как я новичок, мне не удалось найти такой пример. На самом деле, я запутался, если Лисков принцип подстановки и ПЕРЕГРУЗКА вообще могут происходить одновременно. :( @MattCoubrough   -  person Mukit09    schedule 17.12.2014
comment
В C ++ контравариантность аргументов метода рассматривается как совершенно другой метод (перегрузка), поэтому для соблюдения принципа подстановки Лискова вам потребуется, чтобы все подклассы имели одинаковые перегрузки метода.   -  person Matt Coubrough    schedule 17.12.2014
comment
Лисков-Шмисков: передача π в качестве параметра - это то, что я называю несчастным случаем, ожидающим своего часа! (Я уверен, что это всего лишь пример, но все же ...)   -  person AAT    schedule 17.12.2014
comment
@paxdiablo В целом LSP не является правильным или неправильным. Это (как и любой принцип дизайна) руководство. Нарушение принципа - это запах кода. Выполнение этого один раз не обязательно повредит. Но если запах добавится, у вас могут возникнуть проблемы (и, учитывая вашу репутацию, вы наверняка знаете сами).   -  person TobiMcNamobi    schedule 17.12.2014


Ответы (1)


LSP

Принцип замещения Лискова (или LSP) касается абстракции. Представьте себе класс Shape и два класса Square и Rectangle, производных от Shape. Теперь у Shape есть (виртуальный) метод getArea(). Вы ожидаете, что он вернет область, покрытую (конкретной, конкретной!) Фигурой независимо от того, какого она на самом деле типа. Поэтому, если вы вызываете getArea() в экземпляре Shape, вас не волнует, будет ли это прямоугольник, квадрат или любая другая форма, о которой вы можете подумать.

Ответ

Без перегрузки не было бы даже необходимости в чем-то вроде LSP, т.е. ответ отрицательный, перегрузка и LSP не противоречат.

Дизайн

С другой стороны, как указал paxdiablo, применение LSP зависит от конструкции. В терминах приведенного выше примера это означает, что, возможно, по какой-то причине вы действительно заботитесь, есть ли у вас прямоугольник или нет. Что ж, в этом случае LSP говорит, что вы должны подумать о своем дизайне.

Ваш код

Я должен признать, что на данный момент я не совсем понимаю, к чему стремится ваш код. Есть класс Give_Area, который вычисляет площадь круга в зависимости от значения, мм, pi. Второй метод вычисляет квадрат с диагональю Radius? Затем есть класс Square. Если Validity() вернет false, что это будет значить? Может быть, выродившийся квадрат? Мои предложения: пересмотрите свой дизайн. Спросите себя: «С какими классами и объектами я хочу иметь дело?» и "какие объекты реального мира я хочу моделировать?"

Контрпример

Как нарушить LSP показано в Википедии (ссылка выше). Я попробую составить второй пример. Допустим, у вас есть класс Car с методом drive(). Производные классы (RacingCar, Van, ...) могут указывать скорость, ускорение и т. Д. Когда автомобиль заезжает в воду (глубокая вода, озеро, море), машина ломается и вызывается следующий гараж. Теперь вы наследуете класс AmphibiousVehicle. Этот не разбивается о воду и гараж называть бесполезно. Вы этого ожидали? Возможно. Но в противном случае, в зависимости от дальнейшего контекста, я бы подумал о классе Vehicle, который является основой Car. У него был бы метод move(). И drive(), который по-прежнему принадлежит Car, позвонит move() и может (снова ;-)) позвонить в гараж в случае проблемы. И так далее.

person TobiMcNamobi    schedule 17.12.2014
comment
Во-первых, спасибо за ответ. На самом деле я хотел просто перегрузить метод. Я написал этот код в качестве примера. В этом коде нет смысла. Поскольку я новичок в ООП, мне не удалось выяснить, противоречат ли перегрузка и LSP. Хорошо, теперь я знаю, перегрузка и LSP не противоречат. Не могли бы вы привести мне пример, в котором LSP и перегрузка происходят одновременно? Заранее спасибо. Сразу хочу ознакомиться с таким примером. - person Mukit09; 17.12.2014
comment
Спасибо за ваше издание. :) Теперь мне понятно. :) Отличный ответ. :) - person Mukit09; 17.12.2014