Even before I got to the point where I decided I didn't like inheritance, I distinctly recall having conversations about how I felt that using inheritance for anything other than polymorphism didn't usually end up with particularly clean code. I can remember a conversation about this at least as far back as the summer after my freshman year of college, and I don't think I was aware of the idea of "composition" yet, because I remember phrasing my point as something like "inheritance shouldn't be used for 'code-sharing', only for polymorphism".
Out of curiosity, when you say you don't like inheritance, does that mean you never use it at all, or you only use it rarely?
Because even though inheritance often is used in a wrong way, there are definitely cases, where it is the clearest pattern in my opinion.
Like graphic libary things. E.g. everything on the screen is a DisplayObject. Simple Textfields and Images inherit directly from DisplayObject. Layoutcontainers inherit from DisplayObjectContainer which inherits from DisplayObject.
Inheritance here makes a lot of sense to me and I don't see how it could be expressed in a different way without loosing that clarity.
Inheritance is not necessary, but then very few programming constructs are absolutely necessary. The question is does it help program clarity or not. I think that in some cases, used sparingly, it can. The main danger of inheritance is not that it is OO, but that it is not OO enough. It breaks encapsulation by mixing properties and methods between base classes and derived classes without clear boundaries. Composition is safer because it preserves encapsulation. In general, I think that protected abstract methods are a code smell, because they usually indicate close coupling of details that should be kept separate between the base and derived classes. But used correctly, inheritance can be more succinct and convenient.
To be fair, the compiler generally forces you to keep the forwarding methods updated. It can be irritating, but there's little risk of forgetting in a statically-typed language.
Manual forwarding also operates as a forcing function to write small interfaces and to keep different pieces of logic separated in different layers, both of which feel like good design to me. (Though I'm not saying I'd turn my nose up at a terser notation for method forwarding, haha.)
saghm|3 months ago
lukan|3 months ago
Because even though inheritance often is used in a wrong way, there are definitely cases, where it is the clearest pattern in my opinion.
Like graphic libary things. E.g. everything on the screen is a DisplayObject. Simple Textfields and Images inherit directly from DisplayObject. Layoutcontainers inherit from DisplayObjectContainer which inherits from DisplayObject.
Inheritance here makes a lot of sense to me and I don't see how it could be expressed in a different way without loosing that clarity.
o_nate|3 months ago
pjc50|3 months ago
- manually write a bunch of forwarding methods and remember to keep them updated, or
- inheritance.
vips7L|3 months ago
bccdee|3 months ago
Manual forwarding also operates as a forcing function to write small interfaces and to keep different pieces of logic separated in different layers, both of which feel like good design to me. (Though I'm not saying I'd turn my nose up at a terser notation for method forwarding, haha.)
LukeShu|3 months ago
Compare: Ruby mixins or Go embedded struct fields.