1

私はこのコードを持っています:

abstract class Entity
{
// blah-blah-blah
}

abstract class BaseCollection
{
    public void add(Entity entity);
}

そして、私はEntityクラスとBaseCollectionクラスから派生しています。

class User extends Entity
{
}

class UserCollection extends BaseCollection
{
   public void add(User user) { // blah-blah-blah }
}

これはリスコフの置換原則違反の例ですか?もしそうなら、どうすれば問題を解決できますか?

4

3 に答える 3

0

Userサブタイプであるように、そのようなオブジェクトを(経由で)Entity追加することは完全に合理的です-各ユーザーはBaseCollectionUserCollectionEntity

UserCollection一方、期待される場所を通過しBaseCollectionても機能しません。を追加できるようになると期待されEntityますが、-が必要ですUser。つまり、から要素を取得すると、この後にUserCollection取得する可能性があります。Entityあなたが期待するところUser

于 2012-04-17T19:18:15.967 に答える
0

エンティティの他の実装をUserCollectionに追加できなかったため、これはリスコフの置換原則に違反しています。BaseCollectionへの参照を持つユーザーは、UserCollectionsである実装が、User以外のエンティティを提供する場合、爆発することを期待しません。

ナローイングについて明示的に言及し、言語を指定しなかったため、UserCollection.addがBaseCollection.addに取って代わっていると思います。

リスコフの置換原則に従っている場合、メソッドパラメータは共変ではなく、反変である必要があります。 http://en.wikipedia.org/wiki/Liskov_substitution_principle

于 2012-04-17T19:25:20.833 に答える
0

のコントラクトがBaseCollection、そのaddメソッドがから派生したオブジェクトを合法的に渡すことができると指定している場合Entity、の継承されたaddメソッドUserCollectionも同様に行う必要があり、そうしないとLSPに違反します。元のメソッドをから派生した任意のオブジェクトで使用できる場合、タイプのオブジェクトのみを受け入れるオーバーロード(オーバーライドではない)がUserCollection含まれていても、LSPに違反することはありませんが、オーバーロードは特に適切ではない可能性があります。addUseraddEntity

の代わりにadd、問題のメソッドがsetItem(int index, Entity value)ベースsetItem(int index, User value)クラスと派生クラスのようなものであり、コントラクトが同じコレクションから読み取られたオブジェクトでのみ動作することが保証されていると指定されている場合、その読み取りを提供しますのUserCollectionインスタンス以外のものが生成されることはありませんUser。このメソッドは、LSPに違反することなく、setItemのインスタンスではないすべてのオブジェクトを合法的に拒否できます。メソッドがのインスタンスではないものをすべて拒否する場合はUser、のみを受け入れるオーバーロードがあると便利で適切な場合があります。継承されたメソッドは、のインスタンスを識別したことを確認する必要がありますがsetItemuserusersetItemvalueUser、そのタイプの引数を受け入れたオーバーロードは受け入れません。このようなオーバーロードを追加する際の最大の注意点は、同じことを行う2つの封印されていない仮想メソッドを使用しないようにすることです。オーバーロードを追加する場合は、基本クラスのメソッドをオーバーライドしてシールし、渡された引数をtypeに変換してUserから、オーバーロードされたバージョンのメソッドにチェーンする必要があります。

配列は後者の形式のコントラクトと継承にサブスクライブすることに注意してください。タイプの変数は、 ;Animal[]への参照を保持できます。を識別する任意のものをCat[]に格納しようとすると失敗する可能性がありますが、からの読み取りはすべて同じ配列に「適合する」ことが保証されています。これにより、コードは、問題の配列の型を知らなくても、任意の参照型の配列内の要素を並べ替えたり並べ替えたりすることができます。AnimalAnimal[]Cat[]AnimalAnimal[]

于 2014-12-26T20:23:34.163 に答える