web-dev-qa-db-ja.com

LinkedListを拡張するスタック。リスコフ代替原則の違反?

クラスLinkedListには、add_first()、add_last()、add_after()、remove_first()、remove_last()、およびremove()などの関数が存在します。

これで、Push()、pop()、peek()、またはtop()などの機能を提供するクラススタックがあり、これらのメソッドを実装するためにLinkedListクラスのメソッドを拡張します。これはリスコフ代替原則の違反ですか?

たとえば、リンクリストのn番目の位置にノードを追加する場合のadd_after()について考えてみます。これは基本クラスで実行できますが、Stackクラスでは実行できません。ここで事後条件が弱まっていますか、またはスタックの一番上に追加するようにadd_after()メソッドを変更しますか?

また、違反ではない場合、これは悪い設計ですか?そして、LinkedListクラスを使用してスタック機能をどのように実装しますか?

13
jxvmiranda

これで、Push()、pop()、peek()、またはtop()などの機能を提供するクラススタックがあり、これらのメソッドを実装するためにLinkedListクラスのメソッドを拡張します。これはリスコフ代替原則の違反ですか?

いいえ。サブタイプにメソッドを追加しても問題ありません。

たとえば、リンクリストのn番目の位置にノードを追加する場合のadd_after()について考えてみます。これは、基本クラスで実行できますが、Stackクラスでは実行できません。

これはis LSPの違反です。 LSPは、プログラムの望ましいプロパティを変更せずに、サブタイプのインスタンスをスーパータイプのインスタンスに置き換え可能でなければならないことを述べています。サブタイプがメソッドを削除すると、そのメソッドを呼び出すコードはすべてクラッシュします(またはNoMethodError例外、またはそれらの行に沿って何かが発生します)。明らかに、「クラッシュしない」ことが望ましい特性です。

ここで事後条件が弱まっていますか、またはスタックの一番上に追加するようにadd_after()メソッドを変更しますか?

このようにadd_after()メソッドを変更すると、履歴ルールの違反(最も重要なルールです!)になるため、LSP違反の修正には役立ちません。

そして、LinkedListクラスを使用してスタック機能をどのように実装しますか?

構成を使用する。

注:私が上で書いたものすべてonlyは、サブタイピングとサブクラス化を混同する言語に適用されます! LSPは、サブクラスではなく、サブタイピングについてです。 2つを混同しない言語では、subtypeにしない限り、StackLinkedListのサブクラスにすることは完全に許容されます。/LinkedList

31
Jörg W Mittag

すべてはJörgW Mittagによってすでに対処されているので、次の部分について少し詳しく説明します。

ここで事後条件が弱まっていますか、またはスタックの一番上に追加するようにadd_after()メソッドを変更しますか?

基本的に、一部の階層がLSPに違反しているかどうかの質問がある場合、それはあなたがどの契約を結んだかに依存します。それで、どの契約がadd_after 持ってる? 「n番目の位置または最上部にノードを追加する」のように聞こえても、問題がなければ、事後条件は満たされ、LSPに違反していません。それ以外の場合は、LSP違反です。

1
Zapadlo