[Python-ideas] Composition over Inheritance
Steven D'Aprano
steve at pearwood.info
Sat Oct 28 07:51:14 EDT 2017
On Sat, Oct 28, 2017 at 09:09:30AM -0200, Soni L. wrote:
> As recent threads indicate, composition may sometimes be better than
> inheritance. And so I'd like to propose composition as a built-in feature.
>
> My idea is syntax of the form o.[c].m(), where o is an object, c is a
> component, m is a method.
How is that different from o.c.m() which works today?
My understanding of composition is simply setting an attribute of your
instance to the component, then calling methods on the attribute. How
does that differ from what you are describing?
Instead of the classic multiple-inheritence:
class Car(Engine, AcceleratorPedal, GasTank, ...):
pass
which requires each superclass to be designed to work with each other
(e.g. you can't have both EntertainmentSystem.start() and
Ignition.start(), unless you want the ignition to automatically turn on
when the entertainment system does)
we can instead use composition and delegation:
class Car:
def __init__(self):
self.engine = Engine()
self.accelerator = AcceleratorPedal()
...
def start(self):
# Delegate to the ignition component.
self.ignition.start()
etc. Obviously this is just a very loose sketch, don't take it too
literally. Is this the sort of thing you are talking about?
> I am not sure how you'd set components, or test for components,
If you don't know how to set components, or test for them, what do you
know how to do with components?
And how are components different from attributes?
> but I don't think it makes sense to be able to do o.[c][x] or x=o.[c], because
> those break the idea of automatically passing the object as an argument
> (unless we create whole wrapper objects every time the syntax is used,
> and that's a bit ew. also how would you handle o.[c1].[c2] ?).
I'm afraid I do not understand what you are talking about here.
If might help if you give a concrete example, with meaningful names. It
would help even better if you can contrast the way we do composition now
with the way you think we should do it.
I'm afraid that at the moment I'm parsing your post as:
"composition is cool, we should use it; and o.[c].m() is cool syntax, we
should use it for composition; I'll leave the details to others".
> Thus I think o.[c].m() should be syntax sugar for o[c].m(o), with o
> being evaluated only once,
I don't see why you're using __getitem__ instead of attribute access;
nor do I understand why m gets o as argument instead of c.
Wait... is this something to do with Lieberman-style delegation?
http://web.media.mit.edu/~lieber/Lieberary/OOP/Delegation/Delegation.html
http://code.activestate.com/recipes/519639-true-lieberman-style-delegation-in-python/
> as that solves a lot of current issues
> relating to inheritance while introducing very few issues relating to
> python's "everything is separate" (e.g. __get__ vs __getattr__)
> policy.This also makes setting components and testing for components
> fairly trivial, and completely avoids the issues mentioned above by
> making their syntax illegal.
Above you said that you don't know how to set and test for components,
now you say that doing so is trivial. Which is it?
> (Disclaimer: This was inspired by my own programming language,
> Cratera[1], so I'm a bit biased here. Cratera was, in turn, inspired by
> Rust[2] traits.
Traits are normally considered to be a more restricted, safer form of
multiple inheritence, similar to mixins but even more restrictive.
http://www.artima.com/weblogs/viewpost.jsp?thread=246488
> [1] https://bitbucket.org/TeamSoni/cratera
> [2] https://www.rust-lang.org/
--
Steve
More information about the Python-ideas
mailing list