Is Liskov Substitution Principle incompatible with Introspection or Duck Typing?

Do I understand correctly that Liskov Substitution Principle cannot be observed in languages where objects can inspect themselves, like what is usual in duck typed languages?

For example, in Ruby, if a class B inherits from a class A, then for every object x of A, x.class is going to return A, but if x is an object of B, x.class is not going to return A.

Here is a statement of LSP:

Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.

So in Ruby, for example,

class T; end
class S < T; end

violate LSP in this form, as witnessed by the property q(x) = x.class.name == 'T'


Addition. If the answer is “yes” (LSP incompatible with introspection), then my other question would be: is there some modified “weak” form of LSP which can possibly hold for a dynamic language, possibly under some additional conditions and with only special types of properties.


Update. For reference, here is another formulation of LSP that I’ve found on the web:

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

And another:

If S is a declared subtype of T, objects of type S should behave as objects of type T are expected to behave, if they are treated as objects of type T.

The last one is annotated with:

Note that the LSP is all about expected behaviour of objects. One can only follow the LSP if one is clear about what the expected behaviour of objects is.

This seems to be weaker than the original one, and might be possible to observe, but I would like to see it formalized, in particular explained who decides what the expected behavior is.

Is then LSP not a property of a pair of classes in a programming language, but of a pair of classes together with a given set of properties, satisfied by the ancestor class? Practically, would this mean that to construct a subclass (descendant class) respecting LSP, all possible uses of the ancestor class have to be known? According to LSP, the ancestor class is supposed to be replaceable with any descendant class, right?


Update. I have already accepted the answer, but i would like to add one more concrete example from Ruby to illustrate the question. In Ruby, each class is a module in the sense that Class class is a descendant of Module class. However:

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)

14

Here’s the actual principle:

Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.

And the excellent wikipedia summary:

It states that, in a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e., objects of type S may be substituted for objects of type T) without altering any of the desirable properties of that program (correctness, task performed, etc.).

And some relevant quotes from the paper:

What is needed is a stronger requirement that constrains the behavior of sub-types: properties that can be proved using the specification of an object’s presumed type should hold even though the object is actually a member of a subtype of that type…

A type specification includes the following information:

– The type’s name;

– A description of the type’s value space;

– For each of the type’s methods:

— Its name;

— Its signature (including signaled exceptions);

— Its behavior in terms of pre-conditions and post-conditions.

So on to the question:

Do I understand correctly that Liskov Substitution Principle cannot be observed in languages where objects can inspect themselves, like what is usual in duck typed languages?

No.

A.class returns a class.

B.class returns a class.

Since you can make the same call on the more specific type and get a compatible result, LSP holds. The issue is that with dynamic languages, you can still call things on the result expecting them to be there.

But let’s consider a statically, structural (duck) typed language. In this case, A.class would return a type with a constraint that it must be A or a subtype of A. This provides the static guarantee that any subtype of A must provide a method T.class whose result is a type that satisfies that constraint.

This provides a stronger assertion that LSP holds in languages that support duck typing, and that any violation of LSP in something like Ruby occurs more due to normal dynamic misuse than a language design incompatibility.

27

In the context of LSP a “property” is something that can be observed on a type (or an object). In particular it talks about a “provable property”.

Such a “property” could the existence of a foo() method that has no return value (and follows the contract set in its documentation).

Make sure you don’t confuse this term with “property” as in “class is a property of every object in Ruby”. Such a “property” can be a “LSP property”, but it’s not automatically the same!

Now the answer to your questions depends a lot on how stringent you define “property”. If you say “the property of class A is that .class will return the type of the object”, then B actually does have that property.

If, however, you define the “property” to be “.class returns A“, then obviously B does not have that property.

However, the second definition isn’t very useful, as you’ve essentially found a round-about way to declare a constant.

11

As I understand it, there’s nothing about introspection that would be incompatible with the LSP. Basically, as long as an object supports the same methods as another, the two should be interchangable. That is, if your code expects an Address object, then it doesn’t matter if it’s a CustomerAddress or a WarehouseAddress, as long as both provide (e.g.) getStreetAddress(), getCityName(), getRegion() and getPostalCode(). You could certainly create some kind of decorator that takes a different type of object and uses introspection to provide the required methods (e.g., a DestinationAddress class that takes a Shipment object and presents the ship-to address as an Address), but it’s not required and certainly wouldn’t prevent the LSP from being applied.

16

After looking through Barbara Liskov’s original paper, I’ve found how to complete the Wikipedia definition so that LSP indeed could be satisfied in almost any language.

First of all, the word “provable” is important in the definition. It is not explained in the Wikipedia article, and “constraints” are mentioned elsewhere without reference to it.

Here is the first important quote from the paper:

What is needed is a stronger requirement that constrains the behavior of sub-types: properties that can be proved using the specification of an object’s presumed type should hold even though the object is actually a member of a subtype of that type…

And here is the second, explaining what a type specification is:

A type specification includes the following information:

  • The type’s name;
  • A description of the type’s value space;
  • For each of the type’s methods:
    • Its name;
    • Its signature (including signaled exceptions);
    • Its behavior in terms of pre-conditions and post-conditions.

So, LSP only makes sense with respect to given type specifications, and for an appropriate type specification (for the empty one for example), it can be satisfied in probably any language.

I consider Telastyn’s answer to be the closest to what I was looking for because the “constraints” were mentioned explicitly.

5

To quote Wikipedia’s article on LSP, “substitutability is a principle in object-oriented programming.” It is a principle and part of the design of your program. If you write code that depends on x.class == A, then it is your code that is violating LSP. Note this kind of broken code is also possible in Java, no duck typing necessary.

Nothing in duck typing inherently breaks LSP. Only if you misuse it, as in your example.

Additional thought: doesn’t explicitly checking for an object’s class defeat the purpose of duck typing, anyway?

11

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật