アヒル型言語で通常行われているように、オブジェクトを自分自身で検査できる言語では、リスコフ置換原理を遵守できないことを正しく理解できますか?
例えば、Rubyで、クラスの場合B
、クラスから継承A
し、すべてのオブジェクトのためx
のA
、x.class
返すために起こっているA
が、場合x
の目的はB
、x.class
返却するつもりはありませんA
。
LSPの声明は次のとおりです。
ましょうQ(x)はオブジェクトに関するプロパティ証明可能であるxは型のT。次いで、Q(y)は、オブジェクトのために証明可能であるべきであるY型のS Sは、のサブタイプであるT。
たとえば、Rubyでは、
class T; end
class S < T; end
プロパティq(x) =で見られるように、この形式のLSPに違反していますx.class.name == 'T'
添加。答えが「はい」(イントロスペクションとLSPの互換性がない)の場合、私の他の質問は次のようになります。性質。
更新。参考のために、ウェブで見つけたLSPの別の定式化を以下に示します。
基本クラスへのポインターまたは参照を使用する関数は、知らないうちに派生クラスのオブジェクトを使用できる必要があります。
そしてもう一つ:
SがTの宣言されたサブタイプである場合、タイプSのオブジェクトは、タイプTのオブジェクトとして扱われる場合、タイプTのオブジェクトとして動作するはずです。
最後のものには次の注釈が付いています。
LSPはすべて、オブジェクトの予期される動作に関するものであることに注意してください。オブジェクトの予想される動作が明確である場合にのみ、LSPを追跡できます。
これは元のものよりも弱いようで、観察できるかもしれませんが、それが形式化されること、特に予想される動作を誰が決めるかを説明したいと思います。
LSPはプログラミング言語のクラスのペアのプロパティではなく、クラスのペアと特定のプロパティのセットのプロパティであり、祖先クラスによって満たされていますか?実際には、これは、LSPを尊重するサブクラス(子孫クラス)を構築するために、祖先クラスの考えられるすべての使用法を知っている必要があることを意味しますか?LSPによると、先祖クラスは任意の子孫クラスに置き換えられるはずですよね?
更新。 私はすでに答えを受け入れましたが、質問を説明するためにRubyからもう1つの具体例を追加したいと思います。Rubyでは、クラスはClass
クラスの子孫であるという意味で、各クラスはモジュールですModule
。しかしながら:
class C; end
C.is_a?(Module) # => true
C.class # => Class
Class.superclass # => Module
module M; end
M.class # => Module
o = Object.new
o.extend(M) # ok
o.extend(C) # => TypeError: wrong argument type Class (expected Module)