問題タブ [liskov-substitution-principle]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
.net - インターフェイスの実装をテストするために、一連の再利用可能なテストを実装できますか?
私はC#で一連のコレクションクラスを作成しています。各クラスは同様のカスタムインターフェイスを実装しています。インターフェイスの単体テストの単一のコレクションを作成し、それらすべてをいくつかの異なる実装で自動的に実行することは可能ですか?実装ごとに重複するテストコードを避けたいと思います。
これを実現するために、フレームワーク(NUnitなど)またはVisualStudio拡張機能を調べたいと思います。
同じことをしたいと思っている人のために、私はavandeursenの受け入れられた解決策に基づいた私の具体的な解決策を答えとして投稿しました。
oop - OOデザインモデリング
基本クラスとこの基本クラスを拡張する2つのクラスがあり、派生クラスの1つだけが別のオブジェクトとの関係を持っている場合に、ドメインをモデル化する方法。
例:
このモデルはリスコフの原則を破っていますか?class3とのこの関係のためにそう思うので、この関係なしでモデル化する方法、またはこの関係をBaseに移動する方法を理解する必要があります。Class3との関係を処理するためにClass2を処理するプログラムの一部がある場合、class2にキャストしないと基本クラスを操作できません。
これは正しい考えですか?
明確にする...
学習モデルで考えてみましょう。コースとコースクラスがあります。オンラインコースやプレセンシャルコースもあります。プレセンシャルコースでは、このトレーニングの費用に直面する可能性があります。したがって、コストは実在する環境にのみ意味があります。CourseClassesには、範囲の日付または定性的な日付を含めることができます。
今日私はこのモデルを持っています:
今、私はコストに対処する必要があり、この瞬間まで、プレゼンスのコースは私にとって重要ではありませんが、今では、コストはプレゼンスの環境にのみ意味があります。
私の問題は次のとおりです。courseClassのいくつかのものが必要なため、コストモジュールでCourseClassオブジェクトを処理する必要がありますが、QuantitativeCourseClassは財務環境に意味がないため、コストの関係はRangeCourseClassとの関係です。
リスコフについての質問は、このモデルにいくつかの変更を加えるために私のチームをどのように説得するかについてです。
liskov-substitution-principle - オーバーライドされたメソッド引数タイプの絞り込みは、リスコフの置換原則違反ですか?
私はこのコードを持っています:
そして、私はEntityクラスとBaseCollectionクラスから派生しています。
これはリスコフの置換原則違反の例ですか?もしそうなら、どうすれば問題を解決できますか?
php - コードはリスコフの置換原則に準拠していますか?
アップグレードする前に、既存のコードを PHP5.4 でテストしています。PHP が継承モデルを強化したため、次のコードが機能しなくなっていることがわかりました。この引き締めのため、私はSOLID、特にLiskov の代入原則(私は独学のプログラマーです) について読んでおり、コードを改善して将来の「引き締め」に悩まされないようにしています。
PHP 5.3 の結果:
- 違う
- 同等
PHP 5.4 の結果:
PHP 致命的なエラー: A::equals() の宣言は IComparable::equals(IComparable $other) と互換性がある必要があります
次のようにコードを記述すれば、php5.4 エラーを回避できます。
しかし、関数は明らかに引数の型を受け入れないため、修正はリスコフの置換原則に準拠していますか? そうでない場合、必要なことを実行し、同じタイプの 2 つのオブジェクトを比較し、適切な OOD 原則に準拠する継承可能な関数をコーディングするにはどうすればよいでしょうか?
oop - オブジェクト指向メソッドによる型安全性
私は、オブジェクト指向のメソッドを使用してこの問題を正しく解決する方法を考えようとしています。言語は重要ではありません。実際にコードを書きたいのですが、それは私が気にかけているより一般的な原則です。
フィールドを実装したい:操作+、-、*、および/が操作される「数値」のコレクション。さらに、^や循環検出などのより高度な操作を実装できるようにしたいと思います。これらの操作は、(1)特定のフィールドに対して定義する必要はありませんが、(2)効率上の理由から、必要に応じてオーバーライドできます。
これがキャッチです。宣言するのは十分ではありません
型安全性が必要なためです。たとえば、有限体のメンバーを整数に追加することはできません。
おそらく、私が本当に探しているのは、メタオブジェクト、スーパーインターフェイス、または異なるクラス(1つは整数用、1つは7アディック用、1つは有限体F_4用など)を結び付けるものです。あるいは、もっと良いものがあるかもしれません。
NBコードは、それが啓発的であるならば、答えで歓迎されます(奨励されさえします)が、宣言はおそらく十分です:おそらくここの誰もが少なくともいくつかのフィールドのための明白なメソッドを書き出すことができます。
私にとって重要であるが、(明らかに)OOの主要な問題とは関係のない他の条件について説明します。フィールド要素に型情報を伝達させたくないし、さらに軽量にしたい(必要になるかもしれないので)フィールド要素の大きな配列を処理します)。これらのdesiderataは達成できない可能性がありますが、率直に言って、効率よりもここでOOを放棄する可能性が高くなります。しかし、私は目前の特定の問題とは別にこれらの問題について学ぶことに興味があるので、答えは関係なくありがたいです。
java - Liskov Substitution Principle (LSP) を破らないようにするにはどうすればよいですか?
私は、Code Completeの Steve McConnellが言及したものと非常によく似た状況にあります。私の問題が車とトライクに基づいているということだけが、たまたま法律で車のカテゴリに分類されることにあります。今までの車は四輪でした。とにかく、私のドメインは不必要に複雑なので、以下の猫の例に固執するのは簡単です.
ルーチンをオーバーライドし、派生ルーチン内で何もしないクラスを疑ってください。これは通常、基本クラスの設計に誤りがあることを示しています。たとえば、クラス Cat とルーチン Scratch() があり、最終的に何匹かの猫の爪が剥がれて引っ掻くことができないことがわかったとします。ScratchlessCat という名前の Cat から派生したクラスを作成し、何もしないように Scratch() ルーチンをオーバーライドしたくなるかもしれません。このアプローチにはいくつかの問題があります。
インターフェイスのセマンティクスを変更することにより、Cat クラスで提示される抽象化 (インターフェイス コントラクト) に違反します。
このアプローチは、他の派生クラスに拡張するとすぐに制御不能になります。しっぽのない猫を見つけたらどうしますか?それともねずみを捕まえない猫?それともミルクを飲まない猫?最終的には、ScratchlessTaillessMicelessMilklessCat のような派生クラスになります。
時間が経つにつれて、このアプローチは維持するのに混乱を招くコードを生み出します。これは、祖先クラスのインターフェイスと動作が、その子孫の動作についてほとんど、またはまったく意味を持たないためです。
この問題を修正する場所は、基本クラスではなく、元の Cat クラスにあります。Claws クラスを作成し、それを Cats クラス内に含めます。根本的な問題は、すべての猫が引っ掻くという仮定でした。そのため、目的地で包帯を巻くのではなく、発生源でその問題を修正してください。
上記の彼の偉大な本のテキストによると. フォローが悪い
親クラスは抽象である必要はありません
派生クラス
現在、彼は別のクラスを作成することを提案しClaws
ていますが、このクラスを使用して の必要性を回避する方法がわかりませんScratchlessCat#Scratch
。
oop - LSP違反に苦しんでいる状態パターンの代替(または改良)
現在構築中の請求システムの状態ベースの機能に頭を悩ませています。このシステムは、請求書の計算、手動承認、印刷、およびアーカイブをサポートします。
最初は、State パターンを使用してこれをモデル化する必要があると考えました。請求書は、印刷、アーカイブなどを現在割り当てられている状態に委任するコンテキストになります。
しかし、異なる状態 (作成済み、承認済み、印刷済み、アーカイブ済み) が同じ操作をサポートするべきではないため、これは明らかに悪い考えです。たとえば、以前に承認されたことのない請求書を印刷することはできません。サポートされていない操作に対して例外をスローすると、LSP に違反します。この問題の一般的な説明はこちらで見つかりました。
これを適切に実装する方法を知っている人はいますか?
PS: これはつまらない宿題のように聞こえるかもしれませんが、そうではありません。実世界のシステムにはこれが必要です。
design-patterns - リスコフの置換原則は、インターフェースを実装するクラスにも適用されますか?
1)LSPはインターフェイスにも適用されますか?つまり、特定のインターフェイスを実装するクラスを使用しても、期待される動作を得ることができるはずですか?
2)それが実際に当てはまる場合、継承を使用することに対する主な理由の1つがLSPに準拠していますか?おそらく:
a)緩い結合の利点は、LSPに準拠しないリスクを上回ります
b)継承と比較して、クラス(インターフェースを実装する)がLSPに準拠しない可能性ははるかに小さい
ありがとうございました
c# - 継承クラスがLSPのコンテキストで基本クラスの契約を破らないようにする方法は?
C# では - ただし、他の言語にも適用できる可能性があります - LSPのコンテキストでは、別の (変更可能な) クラスから継承するクラスが元の契約を破らないようにするにはどうすればよいですか?
例:またはプロパティ セッターがある場合public
、クラスを継承すると元のコントラクトが壊れるリスクがあります。同じことがメソッドにも当てはまります。internal
protected
virtual
これは、親クラスと継承クラスの所有者が同一人物でない場合に特に当てはまります。コントラクトおよび元の開発者の意図に知識が不足している可能性があるためです。
不変性は唯一の解決策ですか、それとも他の方法がありますか? 私は、継承は「is a」関係ではなく「behaves like a」関係に対応すると考える傾向があります。それは正しい論理的保護ですか?
説明のための例を次に示します。
このトピックを扱っている他の質問に気付きました (たとえば、こちら) が、これらの問題を前もって直面することを避けるために適用する一般的な解決策または適切な方法を探しています。
design-patterns - Liskov Substitution Principleはインターフェースを実装するクラスにも適用されますか?
LSP では、クラスはその基本クラスに置き換え可能であるべきであると述べています。つまり、派生クラスと基本クラスは意味的に同等でなければなりません。
しかし、LSP はインターフェイスを実装するクラスにも適用されるのでしょうか? 言い換えれば、クラスによって実装されたインターフェイス メソッドがユーザーが期待するものと意味的に異なる場合、これは LSP 違反と見なされますか?
ありがとうございました