5

私はOOPの初心者です。最近、リスコフの置換原理について読みました。

以下のコードでは、SquareクラスがGive_Areaを継承しています。Squareクラスに正方形に関連する何かがあるとします (有効性チェックなど)。Give_Areaは、正方形の面積 (4 つの頂点が円の周囲にある) と円の面積を与えます。したがって、Radiusが与えられた場合、円と正方形の領域を印刷する必要があります (その円の周囲に配置された頂点で構成されます)。円の面積を取得するために、パラメーターを使用しました。ただし、正方形の面積を取得する際のパラメーターはありません。したがって、ここでオーバーロードを行いました。

#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?

このコードが違反している場合、Liskov Substitution Principle に違反しないオーバーロードの例を教えてください。

クエリをグーグル検索しましたが、何も見つかりませんでした。:(

前もって感謝します。

4

1 に答える 1

2

LSP

Liskov の Substitution Principle (または LSP) は、抽象化に関するものです。Shape1 つのクラスと 2 つのクラスSquare、およびRectangleから派生したものを想像してくださいShapeShape(仮想) メソッドが追加されましgetArea()た。実際のタイプに関係なく、(具体的な、インスタンス化された!) 形状で覆われている領域を返すことが期待されます。したがってgetArea()Shapeインスタンスを呼び出す場合、それが長方形、正方形、または考えられるその他の形状であるかどうかは気にしません

答え

オーバーロードがなければ、LSP のようなものが必要になることさえありません。つまり、答えはノーです。オーバーロードと LSP は矛盾しません。

デザイン

一方で、paxdiablo さんが指摘したように、LSP の適用は設計に依存します。上記の例に関して言えば、何らかの理由で、長方形があるかどうかを実際に気にしている可能性があります。その場合、LSP は設計について考えるべきだと言っています。

あなたのコード

この時点で認めざるを得ませんが、コードがどこを目指しているのか本当にわかりません。Give_Areaの値に応じて円の面積を計算するクラスがありpiます。Radius2 番目の方法では、対角線として次の正方形を計算します。それからSquareクラスがあります。false を返す場合Validity()、それはどういう意味ですか? 多分退化した正方形?私の提案は次のとおりです。設計を再考してください。「処理したいクラスとオブジェクトは何か?」と自問してください。そして「私がモデル化したい実世界のオブジェクトは何ですか?」

反例

LSP に違反する方法は、ウィキペディア (上記のリンク) で説明されています。2番目の例を作成しようとします。Carmethod を持つクラスがあるとしdrive()ます。派生クラス ( RacingCarVan、 ...) は、速度、加速度などを指定できます。車が水 (深い水、湖、海) に入ると、車は壊れて次のガレージが呼び出されます。次にクラスを派生させますAmphibiousVehicle。これは水で壊れず、ガレージは役に立たずに呼び出されます。あなたはそれを期待していましたか?多分はい。Vehicleしかし、そうでない場合は、さらなる文脈に応じて、のベースであるクラスについて考えますCar。それにはメソッドがありmove()ます。そしてdrive()、まだ所属しているものは、トラブルが発生した場合にガレージにCar電話し、電話move()する可能性があります (再び ;-))。等々。

于 2014-12-17T09:15:38.430 に答える