I don't really understand your thinking here, so I'm not sure how specifically to argue against it, but for now, I at least want to point out that the reason for the delegation in Duck UML diagram isn't for any philosophical "discourse-y" reason, it's because of setFlyBehavior() and setQuackBehavior(). You can't mutate the parent class of an object after creation, at least in Java, which is the language used in the book the diagram comes from, so this case simply requires composition over inheritance for purely mechanical reasons. The same logic doesn't apply for the subclasses of Duck, and I'm not sure why you think these in particular should be replaced with a delegator as well, at least compared to the other uses of inheritance here.
Actually, looking at this diagram again, I just noticed that Duckdoes implement Flyable and Quackable, through Ducklike. Ducks contain another Flyable object and presumably Duck satisfys its own Flyable interface by "decorating" the contained object. I take issue with them using the Flyable interface for Duck's "Fly Behavior", as "something that can fly" is ontologically distinct from a "fly behavior". Using different interfaces for these is part of the appeal of nominal typing. And like, I suppose a duck can hitch a ride on an airplane, but I would represent that as class RidesOn implements FlyBehavior { Flyable ride; /* delegate `fly` to `ride` */ } to explicitly spell out the "is hitching a ride" relationship going on.
I don't really understand your thinking here, so I'm not sure how specifically to argue against it, but for now, I at least want to point out that the reason for the delegation in Duck UML diagram isn't for any philosophical "discourse-y" reason, it's because of
setFlyBehavior()
andsetQuackBehavior()
. You can't mutate the parent class of an object after creation, at least in Java, which is the language used in the book the diagram comes from, so this case simply requires composition over inheritance for purely mechanical reasons. The same logic doesn't apply for the subclasses ofDuck
, and I'm not sure why you think these in particular should be replaced with a delegator as well, at least compared to the other uses of inheritance here.Actually, looking at this diagram again, I just noticed that
Duck
does implementFlyable
andQuackable
, throughDucklike
.Duck
s contain anotherFlyable
object and presumablyDuck
satisfys its ownFlyable
interface by "decorating" the contained object. I take issue with them using theFlyable
interface forDuck
's "Fly Behavior", as "something that can fly" is ontologically distinct from a "fly behavior". Using different interfaces for these is part of the appeal of nominal typing. And like, I suppose a duck can hitch a ride on an airplane, but I would represent that asclass RidesOn implements FlyBehavior { Flyable ride; /* delegate `fly` to `ride` */ }
to explicitly spell out the "is hitching a ride" relationship going on.