Re: LSP and subtype
- From: "H. S. Lahman" <h.lahman@xxxxxxxxxxx>
- Date: Fri, 14 Oct 2005 16:51:26 GMT
Responding to Johansson...
Assume we have a class named Base with a method called foo.
We have a subklass to this Base called Sub also with a method called foo.
I assume that Base.foo() is a concrete implementation that Sub.foo() overrides...
Now to my question:
I'm I right if I say that if the client can use this foo from Sub insted of foo from Base for example by using polymorfism and the client doesn't see any difference then Sub is a subtype of Base.
That is correct. There is only one instance of the root superclass in hand and inheritance resolves the properties for that instance. If the object in hand is a member of Sub, then inheritance provides the override for foo() in all access contexts.
What requirement is on the client program when I say client doesn't see any difference.
Does this actually mean that the client program must be identical when calling foo in Base and when calling foo in Sub.
It doesn't matter to the client if Base.foo() or Sub.foo() is invoked; the client always gets the Sub.foo() because of the override.
However, there are some potential pitfalls here. For example, some poorly formed OOPLs like C++ allow one to instantiate a superclass without specifying a subclass. This creates an inherently ambiguous situation for resolving the properties and the language will have to provide additional rules, such as one always gets Base.foo().
That can create problems for the client who might be more particular about what actual implementation is provided. For example:
[Base]
+ foo()
A
|
+---------+--------+
| |
[Sub1] [Sub2]
+ foo() + foo()where [Sub1] and [Sub2] provide different overrides. Now suppose the Client is indifferent to [Sub1] vs. [Sub2] but does not want to invoke foo() if the instance in hand is just a Base (i.e., no subclass specified). There is no way to express that LSP constraint. Perhaps more important, the diagram provides no clue that such a LSP violation can even happen, which is an invitation to maintenace disasters.
That segues to the notion that the client has to understand _the whole tree_ to access it properly. For example, suppose we can't instantiate Base on a standalone basis and we have:
[Base]
+ foo()
A
|
+---------+--------+
| |
[Sub1] [Sub2]
+ foo()where [Sub2] gets the Base.foo() implementation. Suppose a Client invoking Base.foo() is happy with either implementation so all is well.
Now suppose somebody comes along doing maintenance and decides we need a third implementation:
[Base]
+ foo()
A
|
+---------+--------+--------------+
| | |
[Sub1] [Sub2] [Sub3]
+ foo() + foo()This may break the original Client if the Sub3.Foo() implementation is unacceptable (i.e., an LSP violation from the Client perspective) even though the original Client and its context was not touched. To fix this problem we would need to do further surgery on the tree:
[Base]
+ foo()
A
|
+---------+--------+
| |
[SubA] [Sub3]
A + foo()
|
+-----+------+
| |
[Sub1] [Sub2]
+ foo() + foo()Not only do we have to perform more surgery on the tree, we have to change the calling context in Client to invoke SubA.foo() rather than Base.foo(). Thus the Client has to understand the tree to invoke the correct property implementations
Bottom line: overriding implementations in subclassing was just one of those things that seemed like a good idea at the time but turned out to be a real Bad Idea.
************* There is nothing wrong with me that could not be cured by a capful of Drano.
H. S. Lahman hsl@xxxxxxxxxxxxxxxxx Pathfinder Solutions -- Put MDA to Work http://www.pathfindermda.com blog: http://pathfinderpeople.blogs.com/hslahman (888)OOA-PATH
.
- Follow-Ups:
- Re: LSP and subtype
- From: Andreas Huber
- Re: LSP and subtype
- References:
- LSP and subtype
- From: Tony Johansson
- LSP and subtype
- Prev by Date: Re: Data driven people arguments
- Next by Date: Re: how to draw nested type in UML?
- Previous by thread: LSP and subtype
- Next by thread: Re: LSP and subtype
- Index(es):
Relevant Pages
|