Re: Question on LSP
- From: "H. S. Lahman" <h.lahman@xxxxxxxxxxx>
- Date: Wed, 10 May 2006 17:25:39 GMT
Responding to Kazakov...
Since OO IDs do not have to be explicit attributes (e.g., they can be addresses),
They cannot be addresses, because addresses may change during program
execution. ID has a definite type. One can use for this purpose the type
Machine_Address. But only under some circumstances, namely when
Machine_Address implements the contract of ID. So it is first identity,
then address, in that order, not in reverse.
All the OO paradigm requires is that identity in the problem space be unique. There is no problem with using addresses as identity in the implementation so long as referential integrity is preserved somehow. (Which is primarily an OOP problem.) That will be more difficult if one moves objects, but it is still a routine problem for things like home-grown memory managers.
At the OOA/D level identity is abstracted so that identity need not be explicit. However, consistency with address identity is implicit in the way OO relationships are defined and instantiated at the OOA/D level. IOW, the OOA/D relationship paradigm is /designed/ to be readily implemented with addresses because that is the most efficient mechanism for a memory resident application. That's not true for relationship paradigms like those used in RDBs, which are comparatively inefficient when used in memory.
Look at your types that define objects in the OOPLs in a practical application. Where is the object identity? Most of the time the type definition has no mention of it at all. But every object in memory is uniquely identified by its current address in memory and that identity is what is used ubiquitously by references, offset tables, and whatnot.
It could be true or just a coincidence. Clearly we have a difficult problem
of growing complexity at hand. Old tools and customs stop working. So
people are searching in all corners. My hope is in a great unity, which
would cooptate functional and relational guys.
I don't see that level of cooperation happening real soon. B-) The OO, functional, and P/R construction paradigms are fundamentally incompatible because they have different goals and objectives.
Brain and bowel have different goals and objectives, yet they are perfectly
compatible! (:-))
But brains and bowels are the products of construction and they are constructed differently. The issue here is that the construction methods for the three software paradigms are inherently incompatible so they do not mix. I could solve a problem using an FPL in an OO manner through extensive use of monads and whatnot, but any experienced functional developer would throw up over the result. Similarly, a functional developer could solve a problem using an OOPL in a functional manner with composition and no state variables and I would throw up all over that result.
To what extent the difference in methods influences one in languages and
reverse? Isn't it so that one cannot mix methods just because there is no
way do describe them same language? If the goal to have one language per
one construction method, then indeed there is little hope. But why it
should be the goal?
I think it is far more than just the language. It is about the overall construction paradigm.
For example, one can implement a state machine using either a Moore or Mealy model. But the Moore model is much more natural to OO development while the Mealy model is much more natural to procedural or functional development. The models themselves are mathematically equivalent and completely interchangeable but they make a very big difference to the way one /thinks/ about solving the problem in hand.
But there is still nothing in an OO is-a relationship that says anything about "is substitutable for". In fact, in the Venn Diagram sense objects of one subclass are not substitutable for those in another subclass (i.e., one cannot move objects from one subclass to another). The substitution only enters the picture through polymorphic dispatch during collaboration with objects outside the is-a relationship.
I am not sure, what you say, because we are using very different languages.
But in the model where each object has one type there is no place for
direct types substitutability. Maybe it is what you meant. If so, then
things automatically become polymorphic when instead of a type T we
consider the some set of types related to T (class). A value in that class,
equivalent to some value x of T, is itself polymorphic. That is
substitutable for.
As a translationist I try not to clutter my mind with type systems since they aren't relevant to me. So I am not really qualified to argue with a type maven because I don't fully understand the terminology. For example, your use of 'value' makes no sense to me because a type is always an aggregate of properties (in practice) so it can't have a scalar value.
However, the OO is-a relationship involves multiple distinct types whose property sets are different.
[T]
A
|
+------+------+
| |
[T1] [T2]
Type [T] has some fixed set of properties. Type [T1] has a set of properties that include [T]'s plus some additional specialized properties. Similarly type [T2] has a set of properties that include [T]'s and its own, unique specialized properties. Objects will /always/ be instantiated as either a [T1] or a [T2].
[Languages like C++ that allow instantiation of just a [T] object are broken. One inevitably gets in trouble in during maintenance when subclasses are added because referential integrity is ambiguous; some members of [T] are defined as negatives (i.e., NOT members of the existing subsets). Note that such implications are not so obvious in a type system, which is why we have broken OOPLs. That's one reason why it is important to get the OOA/D right in terms of class sets before going to OOP's type interfaces.]
Types [T1] and [T2] are not substitutable for any of the specialized properties of [T1] and [T2] under any circumstances. However, they are <supposed to be> substitutable for the properties defined by [T]. There are two access possibilities:
Case 1: the client wants only objects that have the [T2] type (or [T1] type). In that case there is no substitutability even though the client accesses the properties of [T] that [T2] has available (i.e., the client navigates a relationship to only [T2] objects). In principle [T1] could implement those [T] properties in a completely unacceptable manner but that would not be relevant to the client because they are never substituted for the [T2] properties. That is, the application will work correctly in all contexts defined by requirements despite the incompatibility.
Case 2: the client wants to access only the [T] properties and does not care which actual type, [T1] or [T2], it has in hand. The client does that by accessing both the [T1] and [T2] types _as if_ they were both instantiations of the [T] type. In that case, the _as if_ access constitutes polymorphic dispatch and type substitution between [T1] and [T2] becomes relevant. Then the application will not work correctly if the [T] properties are not substitutable between [T1] and [T2] objects.
In aggregation? I don't see it as types relationship. But I always wished
to go this way to its logical end, i.e. to have abstract record and array
types. Then teacher would be derived from that type, and student from
associated abstract member type. I suppose it is the same discussion as one
about pointer. The idea is to treat all types relationships uniformly, as
subtyping.
Yech. You must have had a traumatic encounter with functional programming in your formative years. B-)
I had FORTRAN-IV, which was much worse... (:-))
My first program was in '57 on a plug board -- direct hardware 1s and 0s. B-) BAL (Basic Assembly Language) was the Silver Bullet that was supposed to solve the Software Crisis. FORTRAN was still an academic curiosity that all the BAL programmers said couldn't possibly be useful because one couldn't optimize properly.
However, I don't see it as a types relationship either. That's kind of my point about OOA/D not using type systems. B-) However, to implement it at the 3GL level one will have to deal with a type when mapping collaboration messages. But there will still be no type substitution involved because any Teacher always accesses any Student through a single Student type (and vice versa).
Yes, it is not a substitution between Teacher and Student, it is between
Abstract_Referential_Containter and Teacher; Abstract_Referential_Element
and Student. It should be a sort of abstract relational algebra
instantiated in Teacher/Student pair.
You've lost me again because I think you are designing languages rather than solving problems. Surely your 3GL code is not going to have things named Abstract_Referential_Container anywhere in it(?)
Hmm, I could have fat pointers and thin objects. This is actually what
always wished to see in modern OOPL. Technically it means that the type tag
is not stored in the object (that will have no type identity). It is in the
pointer. Note that semantically fat-pointer-to-thin-value is equivalent to
thin-pointer-to-fat-value. Both dispatch, both are dynamically polymorphic.
But it breaks your "is-a" fiction. BTW, having this mechanism, you will be
able to translate your OOA/D "is-a" much more uniformly and efficiently.
I think all you are doing is moving the interface definition (type) out of the object into into the message addressing mechanism.
Abstracting dispatching mechanics? Not really, pointer is an object to me.
It can be of class (fat) or of type (thin) [but never both]. It is just a
consequence of my view on pointers as subtypes.
Fine. But it is all still specific computing space implementations of how one sends an OOA/D message from [Teacher] to [Student].
Yes, see above.
BTW, it is a message sent to the pair (Teacher, Student).
You have lost me again here. I think you must be designing OOPLs again. B-) Relationships can be bidirectional but individual collaborations (messages) among participating objects are always one-way. That is, a Teacher can send a Student a message and a Student can send a Teacher a message over the same relationship, but there aren't any messages to both. OOA/D collaboration is always peer-to-peer (i.e., the 'to' is literal).
As an analogy consider that I can describe any complex behavior with interacting state machines using asynchronous event-based communications. Almost always the state machine actions will be executed at some lower level by making synchronous procedure calls. Does that make a synchronous procedure call inherently asynchronous? No. Like a pointer, it is just an implementation artifact. In this case that call is /inherently/ synchronous even though it implements an asynchronous solution. So the synchronous procedure call has no more to do with asynchronous behavior than a pointer has to do with polymorphic dispatch.
Agree, but why do you think that this supports your point of view and not
mine?! (:-))
LSP can only exist if there is type substitution. One can only have type substitution if there is polymorphic dispatch. Pointers can implement any sort of dispatch.
I consider only one particular case, where target operation is accessed via
pointer. It is a perfect type substitution. It is also polymorphic
dispatch:
If Foo can be called on T and on T* then there exist a polymorphic
subprogram defined on the class T U T*. The polymorphic subprogram has two
bodies:
1. Foo which works on T
2. Foo o "*", which works on T* ("*" is pointer dereferencing operator)
So when you call Foo on a pointer it is a polymorphic call that resolves to
the body 2.
But T* is an intermediary; an indirection. It has nothing to do with and knows nothing about T's properties.
It knows that T has Foo, this is what allows you to do Ptr.Foo (). Only
typeless pointers know [almost] nothing. But we don't want them at all.
T knows, but not T*. T* is simply an indirection to get to a T.
Note that the language allows us to use a name like 'T' on the reference as a mnemonic so that the developer can keep track of what is happening with the indirection. Object* would be perfectly acceptable as an indirection mechanism in providing correct code. But the code would be rather unreadable and the compiler would be less able to detect developer screw-ups. IOW, the 'T' is just syntactic sugar designed to address the developer's problems of maintainability and fallibility rather than the correctness of the solution.
[As it happens, full code generators for UML models treat relationship navigation, including pointer indirection, as an aspect that is orthogonal to class semantics. So they /always/ use Object*. Since one never has to maintain the generated code itself, that is not a problem.]
Foo can only be called on T.
That's Foo 1. Foo 2 can be called only on T*. Foo polymorphic can be called
on any (on one the class).
What?!? We seem to be on different planets again. If T* is pointing to a T, then the only Foo available is the one on T. T* is just an indirection mechanism to get to a T. One /never/ gets a different Foo from accessing through T* than one gets by accessing directly from T. If one could, one has Anarchy rather than an OOPL. B-)
When the client invokes Foo, it is always from T, regardless indirection or what language implementation mechanism is used for addressing a T. That's why modern OOPLs don't make a distinction and always address T.Foo. The fact that the language always introduces a hidden T* is a pure language implementation issue.
Maybe, but I don't want implicit assumptions. If T* is a side effect, then
one cannot talk about identity. If it is an intentional choice to achieve
identity, then that should be made explicitly.
Well, personally I much prefer the always-a-reference approach. It leads to a lot less foot-shooting.
*************
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
Pathfinder is hiring: http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH
.
- Follow-Ups:
- Re: Question on LSP
- From: Dmitry A. Kazakov
- Re: Question on LSP
- References:
- Re: Question on LSP
- From: Dmitry A. Kazakov
- Re: Question on LSP
- From: H. S. Lahman
- Re: Question on LSP
- From: Dmitry A. Kazakov
- Re: Question on LSP
- From: H. S. Lahman
- Re: Question on LSP
- From: Dmitry A. Kazakov
- Re: Question on LSP
- From: H. S. Lahman
- Re: Question on LSP
- From: Dmitry A. Kazakov
- Re: Question on LSP
- From: H. S. Lahman
- Re: Question on LSP
- From: Dmitry A. Kazakov
- Re: Question on LSP
- From: H. S. Lahman
- Re: Question on LSP
- From: Dmitry A. Kazakov
- Re: Question on LSP
- Prev by Date: System Models & Simulation White Paper
- Next by Date: Question about OO definition in a distributed environment
- Previous by thread: Re: Question on LSP
- Next by thread: Re: Question on LSP
- Index(es):
Relevant Pages
|
|