6 ms·
"Catching on" doesn't mean "is the right way to do things". Code reuse is in fact a prime example of a misuse of inheritance
by bradrobertson 5y ago
"Catching on" doesn't mean "is the right way to do things". Code reuse is in fact a prime example of a misuse of inheritance
- Varriount 5y agoHow is it a misuse? And what are the alternatives? To be clear, I do agree with your assertion, however I'm having a hard time actually putting "how/why" into words.
- Spivak 5y agoIt’s a misuse because (if you really are only using it for code reuse) it’s creating an essential relationship between different objects that is actually incidental. A list containing two different subclasses of your avoiding-copy-paste base class is now most likely a logical error.
- deleted 5y ago[deleted]
- findjashua 5y agohow is that different from a list containing 2 implementations of an interface?
- foo_barrio 5y agoThere is no state to track. If there is, 99% composition has worked out way better for me in the long run since I don't have this really strong coupling between two objects.
- username90 5y agoSo you don't have a need for code reuse then since you don't have many types with the same base structure, just say that instead of saying that it is bad.
- catlifeonmars 5y agoThere are often more straightforward ways to reuse code than to use inheritance. ~Two~ three advantages of composition for code reuse: 1. Composition is often more explicit than inheritance. Inheritance is overly magic. 2. Composition avoids incidental coupling of methods. With inheritance this is unavoidable. 3. Composition is more difficult to misuse. Both composition and inheritance have their purposes. In the wild, I’ve seen inheritance misapplied much more often than I have seen with composition.
- Dylan16807 5y ago> A list containing two different subclasses of your avoiding-copy-paste base class is now most likely a logical error. So don't allow those? Supporting inheritance doesn't mean you have to support heterogeneous lists.
- username90 5y agoYou could just as well argue that there should never be any code reuse ever, code reuse always couples objects, code reuse should never be done if the two different parts doesn't have the same purpose. So the same rules for all code reuse also applies for inheritance, if you follow them then there are no problems using inheritance. If you have a set of data kinds which all needs to implement the same fields that has the same purposes then having a list of that parent class doesn't lead to bugs.
- throwaway894345 5y agoI don’t think it’s true that reuse means tight coupling. With composition you can swap out the composed object at runtime and as far as compile time coupling is concerned you can embed an interface to decouple the outer object from the inner object.
- username90 5y agoAll code reuse creates coupling on some level. Creating more abstractions in between reduces coupling but creates code bloat. There is a trade off. For example, if you call the same function from many locations those locations are now coupled since if you change the function you change all of those locations behaviour. Many times that is desirable, in which case it is good coupling. The exact same rule applies to inheritance.
- throwaway894345 5y agoCan you elaborate a bit? How is there coupling between a thing which uses an interface and a thing which implements the interface of the two don’t know about each other? Especially if the interface is implicit à la Go interfaces or structural subtyping?
- username90 5y agoEvery class implementing the interface needs to follow the same interface contract, that is coupling. If you want to change the interface contract for one of them you have to go and change it for all of them or you have buggy interfaces. Every time you create an interface you create a contract for it, if you have the same discipline with inheritance then inheritance isn't an issue. The only problem with inheritance is that people can use it for classes that weren't written to be base classes, and therefore a ton of bad programmers use it for code reuse without thinking about the contract it is supposed to implement at all. With that in mind, allowing inheritance only for abstract classes isn't an issue at all.
- ahartmetz 5y agoCorrectly using a language feature often means using it for more than one reason. Extending superclass code can be well advised in case it also makes sense semantically. Now, I have seen a "mixin" class that just served to provide one relatively independent method, and I turned it into a free function. Much better. In other cases, an extended class works on the whole state of the object. In that case it usually makes sense.
- threatofrain 5y agoWhy is code reuse your prime example for bad inheritance? What should people do instead?
- sabellito 5y agoIn OO languages, inheritance gets the most bang for the buck when used for polymorphism. All code reuse can be expressed with composition and delegation, bringing more flexibility, testability, cohesion, decoupling, etc, etc, etc.
- rectang 5y agoInterfaces with default implementations are better than classes for a number of reasons, including the diamond problem, and that as systems grow large they almost never fit cleanly into an inheritance tree. Fat pointers with two words, one for an interface vtable and one for the object, work really well.
- AnimalMuppet 5y agoIn your view, how is "interfaces with default implementations" different from "inheritance for code reuse"? At a minimum it looks like a virtual function with a default implementation in the base class. If a derived class doesn't override it, isn't that code reuse?
- Spivak 5y agoBecause interfaces don’t confer a relationship between implementations, only that they have some common method signatures.
- username90 5y ago> Because interfaces don’t confer a relationship between implementations Having the interface implement functions does exactly that, so your point only applies for interfaces without implementations.
- 5y ago
- pansa2 5y ago> Code reuse is in fact a prime example of a misuse of inheritance Does that depend on how inheritance works in a particular language? For example, in Python it’s widely believed that inheritance is simply “a tool for code reuse” [0]. [0] https://youtu.be/EiOglTERPEo?t=190 https://youtu.be/EiOglTERPEo?t=190
- signa11 5y agoyup, totally agree. imho, composition is the right (only ?) way to code reuse.
- hota_mazi 5y agoIt's the main reason why inheritance became so popular and so useful. Specialization remains a very common design pattern that is incredibly useful and trivially and intuitively solved with inheritance. No other programming concept (HKT, ad hoc polymorphism, functional programming, etc...) comes close to its elegance.
- rectang 5y ago> Specialization remains a very common design pattern that is incredibly useful and trivially and intuitively solved with inheritance. Beautifully put. That matches up with my own experience learning classical OOP, even if I'm now comfortable with other models.
- ratww 5y agoCode-reuse via "Implementation Inheritance" is completely unnecessary for specialisation or polymorphism. When someone says that "inheritance is bad for code reuse" they're not talking about interfaces, or using inheritance for polymorphism. They're strictly talking about sharing code using implementation inheritance, which is the thing that has been widely criticised for more than 30 years now. One can argue that even the "Template Method Pattern" doesn't fall into "implementation inheritance", since the implementation lives in the subclass. If you read the posts, discussion is way more nuanced than "inheritance bad vs inheritance good".
- hota_mazi 5y agoReusing implementation is the point. Here is more specifically what I meant with my comment about specialization above. There is a class with four methods, three of which are exactly what you need but the fourth one, you need to modify. Solving this with inheritance is trivial (extend and override). Solving this with any other paradigm is... much harder and requires a lot more boilerplate.
- aflag 5y agoIn functional programming you'd just create a new function that takes a value of the same type of those other 3 methods. But anyway, creating a new method without changing any of the methods of the super class I think it's generally ok. The problems arise from modifying methods that the super class already implemented.