I am confused about the composition (has a) relationship. It is clear to me that for example a car class has a
motor class.
My problem is about classes they do not own another class logically, but own them physically in order to use them. You have to have a reference or own a class in order to use its methods, but sometimes it doesn't make sense on a logical level.
For example, let's say there is a class garbage man
and is another class waste container
. The garbage man uses the empty
method of waste container and in order to use its methods, has a reference to the waste container.
Does this mean that garbage man has a (well, multiple) waste container on an object oriented design? I would say garbage man uses waste container, but it confuses me since the garbage man physically has it.
Can someone tell me the logic please?
What is the logic of composition in object oriented design?
92 views Asked by lulijeta AtThere are 2 answers
GarbageMan
doesn't have a WasteContainer
, since a waste container doesn't in any way describe a garbage man or extend its attributes in any way.
I think you're missing an operation here. WasteContainer
has an empty()
method because that's an action which can be performed on it. But GarbageMan
also has an operation. A GarbageMan
can performJob()
. That is where a WasteContainer
comes in. Consider something like this (language-agnostic):
class WasteContainer {
empty() { ... }
}
class GarbageMan {
performJob(Collection<WasteContainer> containers) {
foreach (var container in containers) {
container.empty();
}
}
}
A GarbageMan
knows about WasteContainer
s, since that's part of his job. But he doesn't have WasteContainer
s because maintaining their state isn't part of his job. He performs an operation on them, but doesn't own them.
This can be further abstracted with the use of an interface. For example:
interface Emptyable {
empty();
}
class WasteContainer : Emptyable {
empty() { ... }
}
class GarbageMan {
performJob(Collection<Emptyable> bins) {
foreach (var bin in bins) {
bin.empty();
}
}
}
Now GarbageMan
is further de-coupled from WasteContainer
. There could be many kinds of containers which can be emptied, and a GarbageMan
can handle all of them. The operation is performed identically, just supply a collection of containers to the GarbageMan
and he does his job.
This seems to more closely model the real-world scenario being observed, as opposed to a GarbageMan
owning the state of WasteContainers
. There would likely be some Employer
which manages which WasteContainers
are sent to a particular GarbageMan
instance, there may be different Customer
s who actually own WasteContainer
s or other kinds of Emptyable
s, etc.
There are objects you own and objects you have a reference to. If a containing object owns the contained object, it means the containing object is responsible for the contained object's lifecycle -- creating it, disposing of it (if it's an object that can be disposed of). The owner can also pass ownership of a contained object to another object.
An object you have a reference to is an object you can use, but don't own. The owner will typically give you a reference to the object (by passing it as a parameter to a function call, maybe), and guarantees that the object is in a valid state while you have the reference (some environments assist with this by providing automatic garbage collection)
"Has a" relationships may be either owning or reference, and most computer languages don't include explicit support for the reference/ownership distinction, but it is an important concept to keep straight in design. The UML modeling language does model this distinction: ownership indicates a "composite" relationship, while a reference is an "aggregate" relationship.