|
Re: Extends is evil?
Anthony Lander <anthony.lander@e-x-c-i-t-e.com> wrote in message news:<7_i_a.5092$VG.203290@news20.bellglobal.com>...
> panu wrote:
>
> >> The correct relationship is part-of. People are part-of a ChessClub in
> >> the same way that an engine is part-of a car.
> >
> > Almost, in my opinion. Consider that 'people' is a set/plural
> > but 'engine' is a singular element. Therefore I think we should
> > say: "A set of people can be a *subset* of a ChessClub".
>
> Actually, a chess club has a collection of people; The collection of people
> is a part of the chess club. No different than an engine is part of a car.
True. A chess club may also have a collection of chess boards,
obligations, schedules, etc. It would be absurd to pretend the
ChessClub "is-a" collection of chess boards. It would also be absurd
to pretend it both "is-a" collection of participants and "is-a"
collection of chess boards. While Eiffel (and probably *very* few
other languages) can support this, you basically have to rename every
feature of one of the parent classes, making it look exactly like
aggregation anyhow!
As another poster pointed out quite nicely, the "has-a" is a much
weaker coupling, allowing the collection type to be selected upon its
merits, rather than on the complexity of the protocol that must be
supported in order to subclass. For example, if you want to rank the
players you might have to rip out most of the code in order to inherit
from SortedCollection instead of Set, only to discover that you really
need to inherit from Tree or Heap or Tournament.
Another poster also mentioned substitutability. If the set of players
is immutable you only have to worry about covariance of the parameter
type (Player), not contravariance. However, even when it's supported
by a language it's not always clear how best to use this distinction
(immutability).
In Avail one could have an abstract Club that "has-a" set of players.
ChessClub could be a specialization that also specializes the set of
Players to be a set of ChessPlayers. In fact, in Avail this would
simply be an issue of naming the specialized type "ChessClub". Any
time you had a Club that only contained ChessPlayers, that Club would
automatically have the more specific type "ChessClub". Of course, if
you need to be able to add members to the club you'll have to
introduce a mutable "variable" somewhere, either outside the whole
structure (i.e., a variable that holds the Club's current state) or
between the club and the set of members (i.e., a variable in the Club
that holds the immutable set that represents the current membership).
> > I gather what you're saying is that if there is a proper
> > type-of relationship between two classes, /then/ it is ok
> > (= safe) for the subtype to inherit implementation from
> > its supertype. Right?
>
> Code sharing and subtyping are orthogonal. You can have code sharing
> relationships with no subtyping, and you can have subtyping relationships
> with no code sharing.
>
> In Smalltalk, it so happens that there is only one hierarchy, namely the
> code sharing hierarchy, which forces us to conflate code sharing and
> subtyping. On the surface this looks like a compromise, but in reality it
> is quite elegant: Code sharing (good for the implementor) and
> substitutability (good for the user) are expressed in exactly the same data
> structure!
>
> -anthony (a Wilfian dogmatist if ever there was one)
I agree that these can sit well in the same structure, but that
structure should not be a tree. It should be at least a dag, but more
plausibly a hypergraph, and maybe, just maybe, a hyperset. Note that
my mention above of repeated inheritance in Eiffel above was to show
that that feature of Eiffel would be irrelevant with respect to
attempting to (mis)represent two "has-a"'s as two "is-a"'s, not to
endorse or reject Eiffel's capabilities.
|