Re: Question on LSP
- From: "Dmitry A. Kazakov" <mailbox@xxxxxxxxxxxxxxxxx>
- Date: Mon, 1 May 2006 13:39:38 +0200
On Sun, 30 Apr 2006 16:40:42 GMT, H. S. Lahman wrote:
Responding to Kazakov...
However, I think that is beside the point. The issue here is whether
ClassY* is related to ClassY via subclassing or subtyping.
OK. But I don't want to distinguish subclassing and subtyping.
My assertion
is that in an OO context they are not even remotely related by
semantics. IOW, it would be an apples and photons relationship. So if
one does use types to describe both, then those types will not be
related via subtyping.
So, are we agree that it is the application domain to decide?
The semantics of ClassY* is an identity reference and that semantics is
exactly the same no matter what class the object being identified
belongs to.
Then you should be able to express this semantics in some type-independent
way. I doubt anybody can. OK, let you did it. Then this semantics is still
not about types. As such it is irrelevant to subtyping issue. What is left?
That I still can call methods through pointers. That's subtyping to me,
I don't have a problem with defining ClassY* as a type at the 3GL level.
I just have a problem with saying that type is semantically related to
the type of an object in the ClassY set. It is only semantically
related to types that describe references (e.g., in C++ '&' vs. '*').
Yes. It describes referential semantics. That's a subtype. When it
describes an identity semantics, which wasn't inherited from the target
type, then it is not a subtype (in this part.) I don't see any
contradiction here, because to me there is no full subtypes, they would be
useless. Each new type is both a subtype and not, depending on which part
of semantics is considered.
Calling methods through pointers is subtyping?!? Sorry, that notion is
so alien to me that I don't even know where to push back. B-)
It looks like substitution, it works like substitution... (:-))
To me subtyping is about organizing properties that are shared into
groups and organizing properties that are not shared into other groups.
In the end subtypes simply map to subsets and the tree is just a Venn
Diagram that conveniently allows the distinguishing characteristic of
each set, itself, to be a set (of enumerated properties).
Yes.
No problem again. It is not a LSP subtype in in-methods, clearly null
cannot be passed in there. But I don't care, I have generalized ClassY
exactly for that reason, to have a new value: null. Otherwise, I would use
pointers without null, some languages support them.
But that value is incompatible with the "value" (identity) of a member
of the ClassY set. In an OO context object identity exists in the
problem space and it is necessarily unique to an individual entity.
NULL is not the identity of an entity; it is a negative definition --
the value of there being no entity.
= it is not substitutable. So what? It was designed this way. You stick to
absolute substitutability, but there is no such thing in real programs.
Again no problem. If there is some common ancestor ANY, then why not to
have ANY*? However I don't understand why there should a common ancestor
and why any object needs identify. These do not follow from the problem
space. So it should not be a universally applied relationship. But this is
a debate for another day.
What is the common ancestor between a reference and the object it
references?
The object, it is a parallel hierarchy:
ANY <-- ClassY <--- ClassY*
ANY <-- ANY* <--- ClassY*
I think the tree limbs are:
ANY <-- ClassY <-- Y
ANY* <-- ClassY*
Even if you argue that they are all types of some sort and ANY is the
Mother Of Types, then the only point of common ancestry is ANY, which
has no semantic utility in OO software design. IOW, there is no
practical use for ANY in that situation because it cannot have any
problem space semantics or the tree will inevitably have LSP problems.
Yes, this is an argument against dynamically typed languages and the idea
typeless pointers. But technically it is possible to have.
ANY <-- Class <-- ClassY <-- Y
ANY <-- Reference <-- Object Reference <-- ClassY*
Yes. This is another parallel hierarchy: each specific type is a subtype of
its class.
Apropos of the point below about our having different viewpoints, the
notion of ANY as a Mother Of Types only has academic interest for the
design of languages and whatnot. [The notion is analogous to kludges
like CObject in MFC. One only needs such things explicitly in an
application because of language deficiencies (e.g., to use dynamic_cast
in C++) or because a library designer needs a place to implement
language-specific stuff (e.g., new) behind the scenes. IOW, one should
never, ever have to refer explicitly to CObject or CObect* in
application code.]
I agree, "everything is object" is rubbish. A type without methods is
useless. But there are cases where ANY might have methods. I mean things,
which are methods, but usually aren't considered as ones. It is
1. identity
2. copying
3. other factories
4. things like sizeof()
However, that triggers the thought that you are arguing here on some
basis other than OO development (e.g., linguistics as applied to 3GL
grammars). My position is that in the context of OO abstraction it
makes no <methodological> sense for an identity reference to have a
common ancestor with an object abstracted from the problem space.
This puzzles me. Maybe, the source of disagreement is that you think of it,
as being parametrically polymorphic:
ANY <--- ClassY
Ref <ANY>
Ref <ClassY>
But all forms of polymorphism are equal to me.
No, I wasn't thinking of parametric type substitution (or even the more
general OOA/D parametric polymorphism). I think it is more fundamental.
I see the issues here as being about entity identity and problem space
abstraction. I have the impression you are viewing it from a pure
3GL/type system/language design perspective rather than OO software design.
Sure. You know that I don't believe in nGL. (:-)) I view it is a pure
decomposition into types. Problem space phenomena are mapped to values.
Commonalities are to types. Meta laws are refactored as sets of types.
For example, I don't think LSP is about the mechanics of types, so
talking about details like value vs. object or NULL is really beside the
point. Liskov simply used types as a formalism for expressing the
notion of constraints on substitutability.
But I agree with that.
In my view one cannot even begin to talk about LSP _in practice_ unless
one has a specific problem space in mind. It seems axiomatic to me that
one cannot design a nontrivial subtype tree without LSP conflicts for
all possible contexts of access of the root subtype (i.e., one would
have the ANY problem above if the root had any significant "common"
semantics). [Note that the only reason libraries like MFC work with
CObject providing operations like new is because the context is already
narrowly constrained to a particular language design. Even then, they
break when one brings in another commercial library from a different
vendor!]
IOW, LSP is not practically achievable in the general case, but it has
great value when it is achieved in specific situations. So in a
software development context one needs to have a specific problem space
in mind.
Again, I agree. I also agree with your point about 3GL. nGL forces you to
refrain from considering substitutability as an abstract problem. It is
true that if everything is OK, that will be automatically substitutable.
(We believe that God created our world in accordance with LSP. (:-)) But
how can you tell if your design is OK? To me the substitutability problem
is has a value of its own. I want to be able to handle it at the level of
3GL, without inspecting the problem space. The problem is the power of 3GL.
It seems that LSP is inconsistent with this power. I am not ready to
sacrifice it by going to nGL, even for the sake of LSP conformity.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
.
- Follow-Ups:
- Re: Question on LSP
- From: H. S. Lahman
- Re: Question on LSP
- Prev by Date: Re: Managing multiple instances
- Next by Date: Re: Question on LSP [LONG]
- Previous by thread: Re: Question on LSP [LONG]
- Next by thread: Re: Question on LSP
- Index(es):
Relevant Pages
|