タグ付けされた質問 「liskov-substitution」

オブジェクト指向設計におけるリスコフ置換原理についての質問。

10
これは、リスコフ代替原則の違反ですか?
TaskエンティティのリストとProjectTaskサブタイプがあるとします。タスクはいつでも閉じることができますが、タスクのProjectTasksステータスが[開始済み]になると閉じることができません。UIは、開始済みを閉じるオプションがProjectTask使用できないことを確認する必要がありますが、ドメインにはいくつかの保護手段があります。 public class Task { public Status Status { get; set; } public virtual void Close() { Status = Status.Closed; } } public class ProjectTask : Task { public override void Close() { if (Status == Status.Started) throw new Exception("Cannot close a started Project Task"); base.Close(); } } これClose()で、タスクを呼び出すときに、開始タスクのProjectTask状態の場合は呼び出しが失敗する可能性がありますが、ベースのタスクの場合は失敗しません。しかし、これはビジネス要件です。失敗するはずです。これは、リスコフ代替原理の違反とみなすことができますか?

8
LSP vs OCP / Liskov Substitution VS Open Close
私は、OOPの固い原則を理解しようとしていますが、LSPとOCPにはいくつかの類似点があるという結論に達しました(詳しくは言いませんが)。 オープン/クローズの原則には、「ソフトウェアエンティティ(クラス、モジュール、関数など)は拡張のために開かれているが、変更のために閉じられている必要があります」と記述されています。 簡単な言葉で言えば、LSPはのFooインスタンスをBar派生元のインスタンスに置き換えることができFoo、プログラムはまったく同じように機能することを示しています。 私はプロのOOPプログラマーではありませんが、LSPはBar、から派生しFooたものがその中の何も変更せず、拡張する場合にのみ可能であるように思われます。つまり、特定のプログラムのLSPはOCPが真の場合にのみ真であり、OCPはLSPが真の場合にのみ真です。それは、それらが等しいことを意味します。 私が間違っている場合は修正してください。これらのアイデアを本当に理解したいです。答えてくれてありがとう。

3
サブクラスとサブタイプの違いは何ですか?
Liskov Substitution Principleについてのこの質問に対する最も高い評価の答えは、サブタイプとサブクラスという用語を区別するのに苦労します。また、一部の言語はこの2つを統合しますが、他の言語は統合しないという点も重要です。 私が最もよく知っているオブジェクト指向言語(Python、C ++)の場合、「タイプ」と「クラス」は同義の概念です。C ++に関して、サブタイプとサブクラスを区別することはどういう意味ですか?たとえば、Fooサブクラスではなく、サブタイプであるとしFooBaseます。のfooインスタンスがの場合Foo、次の行になります: FooBase* fbPoint = &foo; 無効になりましたか?

14
クラスの階層でオブジェクトの動作やプロパティを「削除」できるようにする言語やデザインパターンはありますか?
従来のクラス階層のよく知られた欠点は、実世界のモデリングに関しては悪いことです。例として、動物の種をクラスで表現しようとしています。実際にそれを行うといくつかの問題がありますが、解決策を見たことがないのは、サブクラスが、ペンギンが飛べないようなスーパークラスで定義された動作またはプロパティを「失う」場合ですおそらくより良い例ですが、それが私の頭に浮かぶ最初の例です)。 一方では、すべてのプロパティと動作について、それが存在するかどうかを指定するフラグを定義し、その動作またはプロパティにアクセスする前に毎回チェックする必要はありません。Birdクラスでは、鳥が簡単かつ明確に飛ぶことができると言いたいだけです。しかし、その後、どこか恐ろしいハックを使用することなく、「例外」を後で定義できればいいと思います。これは、システムがしばらくの間生産的だったときによく起こります。突然、元の設計にまったく適合しない「例外」が見つかり、それに対応するためにコードの大部分を変更する必要はありません。 それでは、「スーパークラス」とそれを使用するすべてのコードに大きな変更を加えることなく、この問題をきれいに処理できる言語または設計パターンがありますか?ソリューションが特定のケースのみを処理する場合でも、いくつかのソリューションが一緒になって完全な戦略を形成する場合があります。 もっと考えた後、リスコフの代替原則を忘れていたことに気付きました。それができない理由です。すべての主要な「機能グループ」に対して「特性/インターフェース」を定義すると仮定すると、階層のさまざまなブランチに特性を自由に実装できます。たとえば、Flying特性はBirds、いくつかの特殊なリスや魚によって実装できます。 したがって、私の質問は「どのようにして形質を実装しないのですか?」スーパークラスがJava Serializableである場合、たとえば「ソケット」が含まれている場合など、状態をシリアル化する方法がなくても、1つでなければなりません。 それを行う1つの方法は、最初から常にペアですべての特性を定義することです:FlyingとNotFlying(チェックしないとUnsupportedOperationExceptionがスローされます)。Not-traitは新しいインターフェースを定義せず、単純にチェックすることができます。特に最初から使用する場合、「安い」ソリューションのように聞こえます。

9
リスコフの代替原則に違反した場合、何が問題になる可能性がありますか?
私は、リスコフ代替原理の違反の可能性について、この非常に投票された質問に従っていました。Liskov Substitutionの原則が何であるかは知っていますが、開発者としてオブジェクト指向コードを書いている間にこの原則を考えないと、何が間違っているのかが私の心ではまだはっきりしていません。

5
フォールバックのある特別なケースは、リスコフ代替原理に違反しますか?
FooInterface次のシグネチャを持つインターフェイスがあるとします。 interface FooInterface { public function doSomething(SomethingInterface something); } そして、ConcreteFooそのインターフェースを実装する具体的なクラス: class ConcreteFoo implements FooInterface { public function doSomething(SomethingInterface something) { } } ConcreteFoo::doSomething()特別なタイプのSomethingInterfaceオブジェクトが渡された場合、ユニークな何かをしたいと思います(と呼ばれますSpecialSomething)。 メソッドの前提条件を強化するか、新しい例外をスローする場合、それは間違いなくLSP違反ですが、SpecialSomething汎用SomethingInterfaceオブジェクトのフォールバックを提供しながらオブジェクトを特別にケースに入れた場合でもLSP違反になりますか?何かのようなもの: class ConcreteFoo implements FooInterface { public function doSomething(SomethingInterface something) { if (something instanceof SpecialSomething) { // Do SpecialSomething magic } else { // Do generic SomethingInterface …

3
事前条件の強化と事後条件の弱化は、リスコフ代替原理にどのように違反しますか?
次の場合、リスコフの置換原則に違反していると読みました。 前提条件が強化されている、または 事後条件が弱体化 しかし、これらの2つの点がリスコフの代替原則にどのように違反するかは、まだ完全にはわかりません。例を挙げて説明してください。具体的には、上記の条件のいずれかが、サブクラスオブジェクトをスーパークラスオブジェクトに置き換えることができない状況をどのように引き起こしますか?

3
「四角形から継承する四角形」のパラドックスに特定の名前はありますか?
OOPの特定の失敗は、Rectangleを継承するクラスSquareで示されます。論理的には、SquareはRectangleの特殊化であるため、Rectangleから継承する必要がありますが、Squareの長さまたは幅を変更しようとすると、すべてがバラバラになります。 そのケースで何が問題になっているのかを説明する特定の用語はありますか?

3
状態パターンは、リスコフ代替原理に違反していますか?
この画像は、ドメイン駆動のデザインとパターンの適用:C#および.NETの例を使用したものです。 これは、a がその存続期間中に異なる状態を持つことができる状態パターンのクラス図ですSalesOrder。異なる状態間では特定の遷移のみが許可されます。 これでOrderStateクラスはabstractクラスになり、そのすべてのメソッドはそのサブクラスに継承されます。Cancelled他の状態への遷移を許可しない最終状態であるサブクラスを考慮する場合override、このクラスのすべてのメソッドで例外をスローする必要があります。 サブクラスは親の振る舞いを変えてはいけないので、今ではそれはリスコフの代用原則に違反していないのですか?抽象クラスをインターフェイスに変更すると、これが修正されますか? これはどのように修正できますか?

1
Liskov Substitution Principleは、インターフェイスを実装するクラスにも適用されますか?
LSPは、クラスがその基本クラスの代わりになるべきであると述べています。つまり、派生クラスと基本クラスは意味的に同等でなければなりません。 しかし、LSPはインターフェイスを実装するクラスにも適用されますか?言い換えると、クラスによって実装されたインターフェイスメソッドが、ユーザーが期待するものと意味的に異なる場合、これはLSPの違反と見なされますか?

2
現実の世界-リスコフ代替原理
背景:私はメッセージングフレームワークを開発しています。このフレームワークでは次が可能になります。 サービスバスを介したメッセージの送信 メッセージバス上のキューにサブスクライブする メッセージバスのトピックを購読する 現在RabbitMQを使用していますが、近い将来にMicrosoft Service Bus(オンプレミス)に移行することを知っています。 インターフェイスと実装のセットを作成して、ServiceBusに移行するときに、クライアントコード(パブリッシャーまたはサブスクライバー)を修正せずに新しい実装を提供するだけでよいようにします。 ここでの問題は、RabbitMQとServiceBusが直接翻訳できないことです。たとえば、RabbitMQはExchangeとトピック名に依存していますが、ServiceBusは名前空間とキューに関するものです。また、ServiceBusクライアントとRabbitMQクライアントの間に共通のインターフェイスはありません(たとえば、両方にIConnectionがある場合がありますが、インターフェイスは異なります-共通の名前空間からではありません)。 そのため、次のようにインターフェイスを作成できます。 public interface IMessageReceiver{ void AddSubscription(ISubscription subscriptionDetails) } 2つのテクノロジーの翻訳不可能な特性により、上記のインターフェースのServiceBusとRabbitMQの実装には異なる要件があります。したがって、IMessageReceiverのRabbitMq実装は次のようになります。 public void AddSubscription(ISubscription subscriptionDetails){ if(!subscriptionDetails is RabbitMqSubscriptionDetails){ // I have a problem! } } 私にとって、上記の行は、リスコフの代替可能性の規則を破ります。 SubscriptionがIMessageConnectionを受け入れるように、これを反転させることを検討しましたが、RabbitMq SubscriptionにはRabbitMQMessageConnectionの特定のプロパティが必要になります。 だから、私の質問は: これがLSPに違反することを修正できますか? 場合によっては避けられないこと、または何かが足りないことに同意しますか? うまくいけば、これは明確で話題になっています!


1
継承階層でリスコフ置換原理を検証する方法は?
この答えに触発された: リスコフの代替原則では 、 サブタイプでは前提条件を強化できません。 サブタイプでは事後条件を弱めることはできません。 スーパータイプの不変式は、サブタイプに保存する必要があります。 履歴制約(「履歴ルール」)。オブジェクトは、そのメソッド(カプセル化)によってのみ変更可能と見なされます。サブタイプはスーパータイプには存在しないメソッドを導入する可能性があるため、これらのメソッドの導入により、スーパータイプでは許可されないサブタイプの状態変更が可能になります。これは履歴制約により禁止されています。 これらの4つのポイントに違反するクラス階層を誰かが投稿し、それに応じてそれらを解決する方法を誰かが投稿することを望んでいました。 階層内の4つのポイントのそれぞれを識別する方法と、それを修正する最良の方法について、教育目的で詳細な説明を探しています。 注: 私は人々が作業するためのコードサンプルを投稿したいと思っていましたが、問題自体は障害のある階層を特定する方法に関するものです:)

2
LinkedListを拡張するスタック。Liskov Substitution Principleの違反?
クラスLinkedListは、add_first()、add_last()、add_after()、remove_first()、remove_last()、remove()などの関数とともに存在します 現在、push()、pop()、peek()、またはtop()などの機能を提供するクラスStackがあり、これらのメソッドを実装するためにLinkedListクラスメソッドを拡張しています。これは、リスコフ代替原理の違反ですか? たとえば、リンクリストのn番目の位置にノードを追加する場合のadd_after()の場合を考えます。これは基本クラスで実行できますが、Stackクラスでは実行できません。ここで事後条件が弱くなっていますか、それともadd_after()メソッドを変更してスタックの一番上に追加しますか? また、違反ではない場合、これは悪い設計ですか?そして、LinkedListクラスを使用してStack機能をどのように実装しますか?

6
円と楕円の問題は、関係を逆にすることで解決できますか?
持つCircle拡張Ellipse休憩にリスコフSubstition原理、すなわち、あなたはXとYが独立して楕円を描くように設定することができますが、Xは、常に円のためにYに等しくなければなりません:それは事後条件を変更するため、。 しかし、ここでの問題は、Circleを楕円のサブタイプにすることによって引き起こされたのではないでしょうか?関係を逆転させることはできませんか? ですから、Circleはスーパータイプです-メソッドは1つだけですsetRadius。 次に、setXとを追加して、楕円が円を拡張しsetYます。setRadiusEllipseを呼び出すと、XとYの両方が設定されます。つまり、setRadiusの事後条件は維持されますが、拡張インターフェースを使用してXとYを個別に設定できるようになりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.