2 ms·
> When you have UFCS you can toss out 90% of the uses of methods in favor of just plain ole functions. Can those go away if you use inheritance or polymorphism
by motorest 1y ago
> When you have UFCS you can toss out 90% of the uses of methods in favor of just plain ole functions.
Can those go away if you use inheritance or polymorphism, and you need your functions to access protected or private members? I mean, OO is as much about methods as functional programming is about functions.
- zozbot234 1y agoImplementation inheritance is generally a misfeature, especially in modern languages with proper generics. If you insist on having it, you can replicate it manually by using interface inheritance and the generic typestate pattern.
- motorest 1y ago> Implementation inheritance is generally a misfeature (...) Not really. It's value proposition is code reuse. It's not a misfeature just because it breaks a simple explanation.
- elcritch 1y agoYou get about as much reuse from a set of re-usable functions as you get from inheriting implementations. Though I grant that having an object hierarchy does make it a bit more explicit what’s being inherited or needs implementing. However, a OO hierarchy also tends to obscure the actual parent implementations as well. Just having a set of functions from a module generally lowers the number of indirections. In general I find working through a non-OO code base generally easier to grok and understand. Especially the OP culture from Java or C# style OO, even if I’m generally good at understanding OO patterns.
- galangalalgol 1y agoOk, this is what I was trying to say in my sibling post, but without the snark and including the why.
- motorest 1y ago> You get about as much reuse from a set of re-usable functions as you get from inheriting implementations. There's far more to inheritance that code reuse. For example, encapsulation, access control, and static type checking, etc.
- zozbot234 1y agoEncapsulation/access control and static type checking are great features, but you can have them without implementation inheritance.
- zozbot234 1y agoYou only ever need interface inheritance for code reuse. The genuine value proposition for implementation inheritance is, quite unsurprisingly, the same as for typestate and generic typestate, namely better type checking within a single self-contained program module. Implementation inheritance "in the large" remains a total misfeature and should not be used, other than for very tightly defined, extensible "plug in" architectures (where the point of extensibility can itself be treated as a single module). But these are really quite rare in practice.
- motorest 1y ago> You only ever need interface inheritance for code reuse. Not really. Interfaces play no role in invoking member functions, even if they are defined in a base class. Inheritance is used to allow member functions declared in a parent class to be called in a member functions without requiring boilerplate code. Instead of having to duplicate code, inheritance provides a concise way to specify a) this is what I want to reuse, b) this little thing is what I want to change in the implementation. > The genuine value proposition for implementation inheritance is, quite unsurprisingly, the same as for typestate and generic typestate, namely better type checking within a single self-contained program module. No. The value proposition is not requiring any boilerplate code to extend or change any detail in a base class. With inheritance, you just declare the thing you want to add or change, and you do not need to touch anything else. The alternatives being floated fail to meet very basic requirements such as visibility, encapsulation, and access control. > Implementation inheritance "in the large" remains a total misfeature and should not be used (...) Not true. This is a personal belief based on specious reasoning. You need to go way out of your way to ignore the problems that inheritance solved while ignoring the negative impact of the alternatives being floated.
- zozbot234 1y ago> Inheritance is used to allow member functions declared in a parent class to be called in a member functions without requiring boilerplate code. The defining characteristic of implementation inheritance is open recursion. When you call a "member function declared in a parent class" there's no telling what code will actually be run, because that member function may have been overridden at any point in the class hierarchy. There's no way of knowing whether the caller and callee code will agree on the required semantics and invariants involved, or even what these should be for any given case. That's why this is a misfeature for a "programming in the large" scenario. By contrast, these issues can be managed when using implementation inheritance within a self-contained, smaller-scale program module, and then its open recursion behavior, properly managed, matches what we expect from the use of the typestate pattern.
- galangalalgol 1y agoI don't find code reuse to be an unqualified virtue. The most hideous codebases I have been involved with all share an obsession with DRY that destroyed them. Most of them were also really obsessed with extensibility which didn't help. So while implementation inheritance can certainly help with code reuse, I consider that an anti-feature.