inheritance evil

A

Andersen

Hi,

Bloch says in Effective Java that one should try to use composition
rather than inheritance.

Why not *always* use composition then? When should you not?

regards,
Andersen
 
T

Tom Dyess

Andersen said:
Hi,

Bloch says in Effective Java that one should try to use composition rather
than inheritance.

Why not *always* use composition then? When should you not?

regards,
Andersen

I had to look up composition. It used to be called aggregation. I hate when
people change the jargon. Anyhow, both should be used, they aren't mutually
exclusive. You may have mis-read the article. I like to inherit from
HashMap, etc because I don't want to redefine all the interfaces. If I were
to aggregate it, I would either have to make the HashMap public with getters
and setters (which is fine) or redefine the interfaces I wanted to use
against the HashMap (which is a PIA). Did he give a reason for this
proclamation?
 
J

Joona I Palaste

I had to look up composition. It used to be called aggregation. I hate when
people change the jargon. Anyhow, both should be used, they aren't mutually
exclusive. You may have mis-read the article. I like to inherit from
HashMap, etc because I don't want to redefine all the interfaces. If I were
to aggregate it, I would either have to make the HashMap public with getters
and setters (which is fine) or redefine the interfaces I wanted to use
against the HashMap (which is a PIA). Did he give a reason for this
proclamation?

I have done some thinking about this. Yes, it's nice to inherit from
HashMap to avoid typing the methods yourself, but that's really all it
buys you. Inheritance should be a "is-a" relationship. For example,
animals are lifeforms, mammals are animals, dogs are mammals, and
dalmatians are dogs. Each subclass uses *all* the functionality of its
superclass.
Generally, when people want to make their own Map, they extend HashMap
and override a few methods. This ties the internal implementation of the
mapping algorithm to HashMap. The author of the new Map usually doesn't
need this, he/she doesn't even need to know or care what the algorithm
is. As far as the new Map implementation goes, the mapping algorithm
works by magic.
What if some other mapping algorithm works better in some circumstances?
You would need to make a new subclass, which would be totally
incompatible with the original subclass. With aggregation, you only need
to make one class, which implements the Map interface, but only
implements the new features, and leaves the basic Map stuff to an
already existing Map implementation class.
 
H

Heiner Kücker

Andersen
Hi,

Bloch says in Effective Java that one should try to use composition
rather than inheritance.

Why not *always* use composition then? When should you not?

The problem with the inheritance is the creation of breakable inheritance hierarchies.
A little change in your domain problem can destroy your very fragile inheritance hierarchie.

--
Heiner Kuecker
Internet: http://www.heinerkuecker.de http://www.heiner-kuecker.de
JSP WorkFlow PageFlow Page Flow FlowControl Navigation: http://www.control-and-command.de
Java Expression Formula Parser: http://www.heinerkuecker.de/Expression.html
Domain Specific Languages http://www.heinerkuecker.de/DomainParser.html
 
H

Hal Rosser

Bloch says in Effective Java that one should try to use composition
rather than inheritance.

Why not *always* use composition then? When should you not?

When Inheritance makes more sense - use it
When composition makes more sense - use it
use both at the same time when it helps to solve the problem.
 
A

Anthony Borla

Joona I Palaste said:
I have done some thinking about this. Yes, it's nice to inherit from
HashMap to avoid typing the methods yourself, but that's really all it
buys you. Inheritance should be a "is-a" relationship. For example,
animals are lifeforms, mammals are animals, dogs are mammals, and
dalmatians are dogs. Each subclass uses *all* the functionality of its
superclass.

Generally, when people want to make their own Map, they extend
HashMap and override a few methods. This ties the internal
implementation of the mapping algorithm to HashMap. The author
of the new Map usually doesn't need this, he/she doesn't even need
to know or care what the algorithm is. As far as the new Map
implementation goes, the mapping algorithm works by magic.

What if some other mapping algorithm works better in some
circumstances?

You would need to make a new subclass, which would be totally
incompatible with the original subclass. With aggregation, you only
need to make one class, which implements the Map interface, but
only implements the new features, and leaves the basic Map stuff
to an already existing Map implementation class.

You, and others, make valid points, and I would generally agree with what is
being discussed / recommended. However, you are all assuming, I think, that
any inheritance is performed at the top level:

public class MyHashMap extends HashMap ...

In Java, as you probably all know, it is possible to, very easily, use both
inheritance and composition / aggregation [I'll use the term 'containment'
here] by implementing local classes or inner classes.

To return to the earlier example, MyHashMap could be implemented to use a
HashMap subclass via containment; the subclass would be implemented as an
inner class, and relevant MyHashMap methods would delegate to the relevant
subclass instance methods.

Using this, albeit contrived, approach, you've been able to subclass
HashMap, whilst at the same time having quarantined the HashMap subclasses
within MyHashMap, thus haven't 'polluted' the HashMap hierarchy.

Cheers,

Anthony Borla

P.S.

I'm not advocating the above design approach merely highlighting it as a
possibility.

P.P.S.

In UML there actually *is* a difference between aggregation and composition
having to do with whether contained entities are an integral part of the
containing entity. Please refer to:

http://www.softdocwiz.com/UML.htm

for more details on these definitions.
 
T

Tom Dyess

Anthony Borla said:
Joona I Palaste said:
I have done some thinking about this. Yes, it's nice to inherit from
HashMap to avoid typing the methods yourself, but that's really all it
buys you. Inheritance should be a "is-a" relationship. For example,
animals are lifeforms, mammals are animals, dogs are mammals, and
dalmatians are dogs. Each subclass uses *all* the functionality of its
superclass.

Generally, when people want to make their own Map, they extend
HashMap and override a few methods. This ties the internal
implementation of the mapping algorithm to HashMap. The author
of the new Map usually doesn't need this, he/she doesn't even need
to know or care what the algorithm is. As far as the new Map
implementation goes, the mapping algorithm works by magic.

What if some other mapping algorithm works better in some
circumstances?

You would need to make a new subclass, which would be totally
incompatible with the original subclass. With aggregation, you only
need to make one class, which implements the Map interface, but
only implements the new features, and leaves the basic Map stuff
to an already existing Map implementation class.

You, and others, make valid points, and I would generally agree with what
is
being discussed / recommended. However, you are all assuming, I think,
that
any inheritance is performed at the top level:

public class MyHashMap extends HashMap ...

In Java, as you probably all know, it is possible to, very easily, use
both
inheritance and composition / aggregation [I'll use the term 'containment'
here] by implementing local classes or inner classes.

To return to the earlier example, MyHashMap could be implemented to use a
HashMap subclass via containment; the subclass would be implemented as an
inner class, and relevant MyHashMap methods would delegate to the relevant
subclass instance methods.

Using this, albeit contrived, approach, you've been able to subclass
HashMap, whilst at the same time having quarantined the HashMap subclasses
within MyHashMap, thus haven't 'polluted' the HashMap hierarchy.

Cheers,

Anthony Borla

P.S.

I'm not advocating the above design approach merely highlighting it as a
possibility.

P.P.S.

In UML there actually *is* a difference between aggregation and
composition
having to do with whether contained entities are an integral part of the
containing entity. Please refer to:

http://www.softdocwiz.com/UML.htm

for more details on these definitions.

Ok, here's the definition from that link:

The term composition refers to an aggregation within which the "part"s and
the larger "whole" share lifetimes. In other words, if an instance of the
"whole" is destroyed, the connected "part"s are also destroyed.
A given model element can be part of only one composition relationship at a
time.

When would aggregation not follow this definition? The only think I can
think of is if you aggregate an object but forget to free it (in languages
that this is required), or it's just a pointer to another object, for
example:

Patient
PatientList

A PatientList is a collection of Patient, but a pointer/reference to
PatientList is in each Patient so each Patient knows about other Patients.
Wow, how many times can I type Patient in a sentence. Lol.
 
B

Bjorn Abelli

"Anthony Borla" wrote...

I believe that there's a misconception here. There is not a "difference"
between aggregation and composition, as a composition "is-an" aggregation.
The terms "association", "aggregation" and "composition" are simply used to
express different "strenghts" of an association.
The term composition refers to an aggregation within which the "part"s and
the larger "whole" share lifetimes. In other words, if an instance of the
"whole" is destroyed, the connected "part"s are also destroyed.
A given model element can be part of only one composition relationship at
a
time.

When would aggregation not follow this definition?

In *many* cases...

There are a lot of examples where e.g. a Person is aggregated in many lists
at the same time. It would be devastating if the instances were destroyed
together with one of those lists.

Anyway, this type of composition is really another concept than what the OP
asked about, which is the *design pattern* Composition, which can be
compared to e.g. the Decorator pattern.

I don't think that it has been mentioned before in the thread, but IMHO the
discussion on "composition instead of inheritance" shadows another crucial
point of OOP with Java, and that is the importance of using interfaces to
make "unbreakable code", and still be free to change the internal structure
of a class between e.g. composition and/or inheritance.

Just my 2c

// Bjorn A
 
A

Anthony Borla

Tom Dyess said:
Ok, here's the definition from that link:

The term composition refers to an aggregation within which
the "part"s and the larger "whole" share lifetimes. In other
words, if an instance of the "whole" is destroyed, the
connected "part"s are also destroyed. A given model element
can be part of only one composition relationship at a time.

When would aggregation not follow this definition?

I've always interpreted the difference [subtle as it is since both
composition and aggregation are forms of containment i.e. describe HAS_A
relationships] to be based on whether or not the contained object has a
separate existence to the containing object.
The only think I can think of is if you aggregate an object
but forget to free it (in languages that this is required), or
it's just a pointer to another object, for example:

Yes, this is easily modelled in C++ using pointers. Whether it would be
classed as aggregation or composition would depend on whether the containing
class:

* Was the owner - responsible for creating and freeing
the contained entity [hence, composition]

* Merely held a copy of the pointer to allow access to
the entity [hence, aggregation]
Patient
PatientList

A PatientList is a collection of Patient, but a pointer/reference
to PatientList is in each Patient so each Patient knows about
other Patients. Wow, how many times can I type Patient in a
sentence. Lol.

Take, for example, an airport:

class Airport
{
...
private String name_;
private Collection aircraft_;
...
public String getName() { ... }
...
public void addAircraft(...) { ... }
public void removeAircraft(...) { ... }
...
}

An airport could be said to be composed of, among other things, a name_,
because the name_'s existence is inextricably linked with the airport, and
does not exist as a seperate entity.

On the other hand, an airport could be said to contain an aggregation of
aircraft: it may have zero, one, or many aircraft_, and each such entity has
a separate existence [i.e. may be used in other parts of the system].

I suppose it is equally possible to say that an airport is composed of a
collection of aircraft_, but doing so serves only to highlight the use of an
artificial entity to effect this type of relationship.

Regardless of the subtle difference between these relationships [or, slight
variations of the same relationship], in UML they are considered different:
each is indicated using slightly different notation.

Cheers,

Anthony Borla
 
J

John C. Bollinger

Andersen said:
Bloch says in Effective Java that one should try to use composition
rather than inheritance.

Why not *always* use composition then? When should you not?

At least one regular in this forum has advocated making all classes
final. If one actually did that then composition would indeed figure
much more in flexible software designs (and inheritance of
implementation could not be used at all).

In my opinion, however, avoiding inheritance altogether is too extreme a
position. I don't know what Bloch's exact words were, but I'd say it
something like this: look for opportunities to use composition instead
of inheritance. Sometimes inheritance is clearly the right way.
Sometimes composition has great advantages. My advice, which I think is
similar to Bloch's, is to lean toward composition when the better choice
is otherwise unclear.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top