...the other major concept you should recognize is that of object composition.
This is simply the construction of objects that contain others: encapsulation of several objects inside another one. While many beginning OO programmers use inheritance to solve every problem, as you begin to write more elaborate programs, the merits of object composition become apparent. Your new object can have the interface that is best for what you want to accomplish without having all the methods of the parent classes."
Does anybody have a code example to illustrate this premise?
SCJP 1.4 (93%)<br />SCJD (In progress. It can run, but it can't hide...)
A prominent example is java.util.Stack. Having it inherit from Vector was an error, it should have used composition.
If they had used composition, Vector now could use an ArrayList, LinkedList or even an array internally. Because they choose to use inheritance, they can't make that change, because it could break existing clients.
Additionally, the interface of Stack is poluted with methods from Vector that actually don't make sense for a Stack.
The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Joined: Dec 09, 2000
Joined: Jul 11, 2001
As an aside, this heuristic actually only applies to interface inheritance. Pure implementation inheritance (such as C++ private inheritance) doesn't have that problem. Java doesn't support pure implementation inheritance, though - you always also inherit the superclasses interface.
I found another scary example in my company. Somebody started out with a base class that could connect to a database. He extended it with another class that could execute a query. He extended that with any class in the system that needed database data. So now any business object that happens to need data "is a" database aware thingy plus whatever business logic it adds.
It would have been much better to have a data accessor that any other object could "have" or use. Then a business object could extend an appropriate abstract business class instead of always extending a database thing. And if "data accessor" was an interface we could plug in data accessors for LDAP and MQ-Series and flat files without breaking the business classes.
The "is a" heuristic is not 100% reliable for inheritance, but it's a good sanity check now and then. SecurityManager "is a" DatabaseAccessor just doesn't sound right.
A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Personally, I dislike the "has-a" notion as a design notion, because I think it's misleading. I have less of a problem talking about an entity having another entity from an analysis point of view. Whether the "has-a" relationship than is implemented as composition or something else then is a technical decision - "has-a" really isn't precise enough to be of much help when you think about design, in my opinion.