Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Inheritance makes some sense, but composition is much, much easier to understand and work with. Inheritance has well documented problems that composition does not. It’s not so much about being object oriented or not, at least not directly.

I could elaborate, but others have said it better anyways.

https://en.m.wikipedia.org/wiki/Composition_over_inheritance



but composition is much, much easier to understand and work with.

The article you linked mentions IMHO the biggest disadvantage:

One common drawback of using composition instead of inheritance is that methods being provided by individual components may have to be implemented in the derived type, even if they are only forwarding methods

Code whose only purpose is to "appease the design" and otherwise does absolutely nothing of value is a strong-enough negative reason. It's pure bloat, overhead that gets in the way of both programmers trying to understand/debug and machines trying to execute.

Too much inheritance can lead to a "where is the method" problem, but I think that's still better than the alternative of dozens upon dozens of lines of otherwise useless code, because the former at least does not increase the amount of code that needs to be written/debugged/maintained.


That isn't an inherent issue of composition though. You could say

   {...students(ajaxDb), ...teachers(ajaxDb)}
to create an object that can handle both students and teachers. Or you could say

   public class StudentsAndTeachers extends Students implements IStudents, ITeachers {
       private _teachers;
       public constructor(Database db, Teachers teachers) {
           super(db);
           _teachers = teachers;
       }
       public getTeacher(TeacherId teacherId) {
           return _teachers.getTeacher(teacherId);
       }
   }

   new StudentsAndTeachers(ajaxDb, new Teachers(ajaxDb));
It seems clear that the features of the language define what is verbose and what isn't verbose. Even the inheritance in the language that encourages inheritance is more verbose than the composition in the neutral language.

(More likely, you wouldn't write this, but every example that is colloquial in inheritance is non-colloquial in composition. The composition oriented solution can be used cleanly with strong guarantees provided to its users; whereas all inheritance oriented solutions are so tacky and hard to use that you will demand a framework with dependency injection which half your team won't be able to understand and will have to treat as magical incantations.)


Composition is entirely capable of creating an ad-hoc informally specified bug-ridden slow implementation of inheritance.


That relates to my comment in what way?


Pretty obviously, ridiculous_fish is claiming that that's what you're doing.

Note: I'm not saying that ridiculous_fish is right. But it's pretty obvious that that's the claim.


How often do you need to write methods just to forward to another method that _stay_ that way, and don’t evolve more logic later on? I avoid inheritance like the plague, but I feel like I don’t really write forwarding methods very often.


Few of design patterns work exactly like that: forward to another method. Evolving that API afterwords is not a lot of hassle. I really fail to see the argument here..


This, 100 times. Program for enough years and you'll find composition such a breath of fresh air. But like any pattern/design, the proof is in the pudding; as in, crap code can be written in any shape or format.


I'm curious why you find it a breath of fresh air? The Wikipedia link in the post you're responding to specifically states that composition over inheritance is an OOP principle. If one needs to abandon OOP to make use of composition, was OOP actually what was being done or was it instead an exercise in creating an class-based taxonomy? (a lot of people seem to fall into this trap)


It's the way OOP was used from what I saw 10-20 years ago. It was all inheritance, from uni course to patterns used etc.

I've only fell into composition when I got into video game development. We saw it a bit more with Silverlight but now it's such a clear movement (composition over inheritance) that it's in my resume's motto.


It's the way many OOP languages went, but it's not intrinsic to OOP.

I recall encountering Emerald in the late 1980s. Here's its 1989 paper on composition over inheritance (code reuse wise): http://www.emeraldprogramminglanguage.org/Raj_ComputerJourna...


Composition should be favored over inheritance whenever feasible. It is not always feasible so many use for inheritance remain.

What you can do is make composition easier. Kotlin does this with its delegation system: https://kotlinlang.org/docs/reference/delegation.html


Of course, it is possible to totally eschew inheritance as a language feature. Go does it nicely and I can’t think of many circumstances where modeling my code has suffered as a result, usually the opposite.

That said I don’t claim inheritance to be useless by any means, and I would not use Go for every kind of software.


I didn't claim it is impossible either :)

I kinda agree. Still, for an imperative language I think it's a tool I'd like to have in my toolbox, or at least it needs a compelling alternative, which I don't think Go has (1). Of course there are many cases in which you can do perfectly without.

(1) I know it has composition through struct embedding, but not real inheritance: a method delegated to the embedded struct can't call back a method on the embedder automatically. If you do know of some other means in which Go can replace this kind of inheritance, I'd be happy to hear about it.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: