Live data from Hacker News

Why composition is often better than inheritance

joostdevblog.blogspot.com

21–30 of 97 posts

Re: Why composition is often better than inheritance

#21
post #9

I think this is a tooling issue. People initially tend to favor inheritance because it looks cleaner than composition. Mixing a lot of unrelated code in the same class makes things hard to find. (which method applies to which composed object?) In languages that build in a concept of traits/mixins however, this isn't an issue.

I think so too. In JS it's rather easy to compose objects. In Java it feels clunky, you code looks kinda wrong when you done.

I don't quite understand this. In my opinion JS "classes", if you want to call them that, look, feel and act very clunky. My opinion, of course... Please could you explain to me how you feel Java "classes" feel clunky and look wrong? I'm genuinely curious, and open to being convinced.

Note I substituted your usage of "objects" with classes, because they're vastly different concepts. I know, murky water when it comes to JS, but still.

Re: Why composition is often better than inheritance

#22
post #20

In Python, we use mixins. Mixins can only inherit from 'object' and nothing else, like this: class PhysicsobjectMixin(object): def update_physics(self): pass def apply_konckback(self, force): pass def get_position(self): pass class FightMixin(object): def attack(self): pass def defend(self): pass class TalkMixin(object): def say_something(self): pass class Character(PhysicsobjectMixin, FightMixin, TalkMixin): pass cl…

I don't see the difference to interfaces.

[deleted]

Re: Why composition is often better than inheritance

#23
post #20

In Python, we use mixins. Mixins can only inherit from 'object' and nothing else, like this: class PhysicsobjectMixin(object): def update_physics(self): pass def apply_konckback(self, force): pass def get_position(self): pass class FightMixin(object): def attack(self): pass def defend(self): pass class TalkMixin(object): def say_something(self): pass class Character(PhysicsobjectMixin, FightMixin, TalkMixin): pass cl…

I don't see the difference to interfaces.

The stuff you mix in has code. Interfaces do not.

Re: Why composition is often better than inheritance

#24

In Python, we use mixins. Mixins can only inherit from 'object' and nothing else, like this: class PhysicsobjectMixin(object): def update_physics(self): pass def apply_konckback(self, force): pass def get_position(self): pass class FightMixin(object): def attack(self): pass def defend(self): pass class TalkMixin(object): def say_something(self): pass class Character(PhysicsobjectMixin, FightMixin, TalkMixin): pass cl…

Is that just multiple inheritance, or are mixins something else?

Re: Why composition is often better than inheritance

#25
It's pretty much the same example I used here a couple of days ago: https://news.ycombinator.com/item?id=7976227

Game development seems to be the poster child for composition over inheritance.

Here's a lengthy article that explains it way better (IMHO): http://gameprogrammingpatterns.com/component.html

Re: Why composition is often better than inheritance

#26
post #20

In Python, we use mixins. Mixins can only inherit from 'object' and nothing else, like this: class PhysicsobjectMixin(object): def update_physics(self): pass def apply_konckback(self, force): pass def get_position(self): pass class FightMixin(object): def attack(self): pass def defend(self): pass class TalkMixin(object): def say_something(self): pass class Character(PhysicsobjectMixin, FightMixin, TalkMixin): pass cl…

I don't see the difference to interfaces.

The difference is that those aren't interfaces. I'm confused by the question?

Re: Why composition is often better than inheritance

#27
post #24

In Python, we use mixins. Mixins can only inherit from 'object' and nothing else, like this: class PhysicsobjectMixin(object): def update_physics(self): pass def apply_konckback(self, force): pass def get_position(self): pass class FightMixin(object): def attack(self): pass def defend(self): pass class TalkMixin(object): def say_something(self): pass class Character(PhysicsobjectMixin, FightMixin, TalkMixin): pass cl…

Is that just multiple inheritance, or are mixins something else?

Multiple inheritance with your discipline to not do more complicated things. Only inherit from base 'object', nothing else, so you will have no complicated inheritance problems.

Re: Why composition is often better than inheritance

#28
post #21
post #9

Earlier quoted context omitted.

I think so too. In JS it's rather easy to compose objects. In Java it feels clunky, you code looks kinda wrong when you done.

I don't quite understand this. In my opinion JS "classes", if you want to call them that, look, feel and act very clunky. My opinion, of course... Please could you explain to me how you feel Java "classes" feel clunky and look wrong? I'm genuinely curious, and open to being convinced. Note I substituted your usage of "objects" with classes, because they're vastly different concepts. I know, murky water when it comes…

My point was, classes and inheritance feel natural in Java. Object-Composition feels natural in JS.

Re: Why composition is often better than inheritance

#29
post #20

In Python, we use mixins. Mixins can only inherit from 'object' and nothing else, like this: class PhysicsobjectMixin(object): def update_physics(self): pass def apply_konckback(self, force): pass def get_position(self): pass class FightMixin(object): def attack(self): pass def defend(self): pass class TalkMixin(object): def say_something(self): pass class Character(PhysicsobjectMixin, FightMixin, TalkMixin): pass cl…

I don't see the difference to interfaces.

With interfaces, the above example would look like this:

    from abc import ABCMeta   

    class PhysicsobjectMixin(ABCMeta):
        @abstractmethod
        def update_physics(self):
            pass
        
        @abstractmethod
        def apply_konckback(self, force):
            pass

        @abstractmethod
        def get_position(self):
            pass


    class FightMixin(ABCMeta):
        @abstractmethod
        def attack(self):
            pass

        @abstractmethod
        def defend(self):
            pass

    
    class TalkMixin(ABCMeta):
        @abstractmethod
        def say_something(self):
            pass


    class Character(PhysicsobjectMixin, FightMixin, TalkMixin):
        def update_physics(self):
            pass

        def apply_konckback(self, force):
            pass

        def get_position(self):
            pass

        def attack(self):
            pass

        def defend(self):
            pass

        def say_something(self):
            pass


    class Pickup(PhysicsobjectMixin):
        def update_physics(self):
            pass
        
        def apply_konckback(self, force):
            pass

        def get_position(self):
            pass


    class Projectile(PhysicsobjectMixin):
        def update_physics(self):
            pass
        
        def apply_konckback(self, force):
            pass

        def get_position(self):
            pass

This is not DRY at all. I like mixins much better.

Re: Why composition is often better than inheritance

#30
While it's possible to overuse inheritance, I don't think replacing it with composition is all that much better, and in addition all those forwarding methods that do nothing more than call another (could they even be optimised out?) are a great example of code that would need to be written, consuming resources like programmer time, but otherwise serves no true useful purpose to the functionality of the software. The complexity only changes form, so instead of tracing the flow through an inheritance hierarchy you're just doing it through chains of forwarding methods. It's for this same reason I don't believe so much his argument for readability and short classes - breaking everything up does not make things simpler, it makes the complexity spread out over a larger area; while it may be true that it is easier to understand an individual piece, it becomes more difficult to understand the system as a whole. This is especially important when debugging, where "can't see the forest for the trees" is a big hindrance.

I think his example of flexibility is the strongest argument for composition, because in that case the forwarding methods are not a waste - they would need to do (useful) work to determine which of the multiple composited objects they would need to work with.

Being mostly a C programmer who does OO-things, I use inheritance when it's obvious that most of the "methods" will be passthroughs to the "superclass", and composition when there is something more that needs to be done. Also, as I am not constrained by the OO model/conventions of the language, it's more flexible in that I can do things like "inherit" multiple times and even change that at runtime, so there is really no strict separation between composition and inheritance; to me, it's just "which function do I set this to point to."

Post reply on HN