Re: Aggregation vs composition
From: Matthias Hofmann (hofmann_at_anvil-soft.com)
Date: 05/11/04
- Next message: Matthias Hofmann: "Re: Aggregation vs composition"
- Previous message: Universe: "Excuse Please - Re: Why is OO Popular?"
- In reply to: Daniel T.: "Re: Aggregation vs composition"
- Next in thread: Matthias Hofmann: "Re: Aggregation vs composition"
- Reply: Matthias Hofmann: "Re: Aggregation vs composition"
- Reply: Daniel T.: "Re: Aggregation vs composition"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Tue, 11 May 2004 13:49:05 +0200
Daniel T. <postmaster@eathlink.net> schrieb in im Newsbeitrag:
postmaster-B05EDC.19182809052004@news1.west.earthlink.net...
> >
> > Complaining about what? I never gave you any documentation...
>
> Every time you tell me that the diagram shows [A]<#>--->[B] and then
> tell me about how A cannot delete a B without permission from some other
> object. You are specifying documenation that contradicts the diagram.
This must be a misunderstanding. The diagram says that A is responsible for
deleting B, it doesn't say that A does so without permission. The permission
is given by calling a method of A that deletes B or by destroying A itself.
>
> Is the following code correct?
>
> int* a = new int;
> int* b = a;
> delete a;
> *b = 5;
>
> Of course not. Yet you tell me that "Holding a reference does definitely
> not influence the corresponding object or its lifetime."
This is exactly my point: in your example, you are not just holding a
reference, you are using it. The holding of the reference does not have any
influence.
>
> It seems to me that having 'b' hold the same object that 'a' holds
> absolutly *does* influence the corresponding object, *and* its lifetime!
> Something is very wrong here, either 'a' should not have been deleted,
> or 'b' should have dropped its reference to the object. I call that a
> big influence.
Again, not holding the reference but using it causes the influence. Of
course it is good coding style to set both pointers to 0.
>
>
> > > Here is another example:
> > >
> > > class Car {
> > > Engine* e;
> > > bool canDelete;
> > > public:
> > > Car(): e( 0 ), canDelete( true ) { }
> > > ~Car() { delete e; }
> > > void doneWithEngine() { canDelete = true; }
> > > Engine* getEngine() { canDelete = false; return e; }
> > > };
> > >
> > > In the above class, the Car can only delete 'e' if canDelete is true,
or
> > > '~Car' is called.
> >
> > This corresponds with my example of the file system. getEngine() and
> > doneWithEngine() is like opening and closing a file. While it is open,
you
> > cannot delete it. I agree so far.
>
> "... you cannot delete it." Don't you mean "the Car" cannot delete it?
Yes, the Car cannot delete it, if you like that better. Unless, of course,
you destroy the Car.
>
> > > Obviously, as long as canDelete is true the engine can
> > > do whatever it wants to 'e' but when 'canDelete' is false, what object
> > > is *truly* responsible for the disposition of the 'e'? Not Car, that's
> > > for sure...
> >
> > Well, don't be so sure. It is still Car who is responsible, calling
> > getEngine() has just deferred the moment when it will do the deletion.
>
> Well we must agree to disagree then. It doesn't "defer" the moment of
> deletion, it absolutly forbids any possibility of the Car deleting the
> engine. The only possible way for the engine to be deleted once
> canDelete is false is if ~Car is called. Let's think about that:
Yes, it does defer the moment. Sometime either someone calls
doneWithEngine() or, as you say yourself, ~Car is called.
>
> void killEngine(Engine* e) {
> detele e;
> }
>
> If the above function is the only bit of code that actually calls delete
> on Engine objects, is it solely responsible for all engine deletions?
> No, 'killEngine' just becomes a synonym for 'delete e'.
>
> The same is true with the Car class, when canDelete is false, ~Car just
> becomes a synonym for "delete e"
So you are saying that it's not Car that deletes the Engine, it's Car's
destructor. That's like saying that it's not me who is typing this sentence,
it's my fingers.
>
> > > So here we have a class (Car) that is decidedly *not* solely
responsible
> > > for the disposition of its part, even though it's the only one that
> > > calls delete on that part, and is always the last one to hold a
> > > reference to that part. The relationship is Aggregation, not
Composition
> > > *because the part is being shared*.
Composition does not forbid sharing, as long as the part is not shared by
another aggregation. That means that no two Car objects are allowed to hold
a pointer to the same Engine. You are saying that the relationship is not
composition, although all necessary criteria are met.
> >
> > My disagreement should be obvious.
>
> At this point, we must end the discussion. We both see the exact same
> class and agree at every point. Except, you insist that Car is *solely*
> responsible for Engine because the Car class is the only place where the
> delete is.
Well, if that doesn't indicate sole responsibility, what else does? By the
way, you may call delete on the Engine if you have previously removed it
from the Car, for example by assigning another Engine to the Car or setting
its Engine pointer to 0.
> You have even gone so far (in another post) as to say that
> the whole concept of Compostion is irrelevent in a language that doesn't
> have a delete operator...
I think I remember that this was actually a question of mine. I only have
experience in C++, so I cannot give you an example of composition in other
languages. But again, look at my folder/file example, which should be a
composition in every language.
> I see a larger picture, Car is very limited as
> to when it can delete the Engine. Despite the fact that the car is the
> last object to see the engine alive, it can only delete the engine if
> spifically allowed to by some other object. I feel sorry for anyone who
> is told they are responsible for doing something, while at the same time
> being informed that they are absolutly *not* allowed to do that thing
> unless spicifically prompted by someone else. I don't call that
> responsibility.
What you are describing as responsibility is what I call arbitrariness.
Responsibility, at least in the context of composition, means doing what
others expect you to do. Composition does indeed imply limitations, the
whole is responsible for deleting the part, but it does so when it is
instructed to, not when no one is expecting it.
>
> Another real world example. I'm driving to Michael's house, you are in
> the passenger seat. You know where Michael's house is and I don't. At
> every intersection, you tell me "turn right", "turn left" or "go
> straight". Who is responsible if we get lost? By your logic, I'm
> responsible because I'm driving...
Let me try to figure out what you mean by this comparison:
You, as the driver, are the one taking my commands, like an objects does a
delete when someone calls a corresponding method on it. I guess that's what
you are trying to say.
According to my logic, you are not responsible if we get lost. Your
responsibility is to drive where I am telling you. If I say "turn right", I
expect you to do so, like I expect your Car class to delete its Engine if I
call "Car::DeleteEngine()".
If it turns out later that the Engine is still needed, then it's the caller
of Car::DeleteEngine() who is responsible for the mess. The Car is only
responsible for the deletion of the Engine.
Best regards,
Matthias
- Next message: Matthias Hofmann: "Re: Aggregation vs composition"
- Previous message: Universe: "Excuse Please - Re: Why is OO Popular?"
- In reply to: Daniel T.: "Re: Aggregation vs composition"
- Next in thread: Matthias Hofmann: "Re: Aggregation vs composition"
- Reply: Matthias Hofmann: "Re: Aggregation vs composition"
- Reply: Daniel T.: "Re: Aggregation vs composition"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]