[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