7 ms·
I’ll go out on a limb and posit that there are virtually no valid uses of (implementation) inheritance. Perhaps one valid use is getting rid of delegation boile
by throwaway894345 5y ago
I’ll go out on a limb and posit that there are virtually no valid uses of (implementation) inheritance. Perhaps one valid use is getting rid of delegation boilerplate (e.g., normally you would compose one object inside another but you want the outer object methods to delegate to the inner object methods but you don’t want to have to write N function definitions that just call the same methods on the inner object so instead your outer object inherits from your inner object). This problem is better solved by something like Go’s struct embedding since it doesn’t do anything more than this kind of automatic delegation.
And if you get rid of inheritance, there is very little left to distinguish OOP from procedural programming like one would do in C or Go. And this is the semantic problem: no one really agrees on what OOP is and proponents will rebut any criticism with “that’s not true OOP”. Any definitions of OOP that aren’t easily assailable are also indistinguishable from other existing paradigms.
Downvoters: i’m very interested in your opinions about why I’m wrong and specifically when you think inheritance is appropriate. Everyone says “there’s a time and a place!” but no one articulates when/where beyond cat/dog/animal toy examples.
- pulse7 5y agoSome cases where inheritance may be useful: UI widget libraries, graphical/drawing objects, (very similar) stream implementations. All this can of course be done without inheritance, but with inheritance it is much more elegant.
- throwaway894345 5y agoThank you for responding. I probably agree with the widget library example, but even here a widget library is just one way of implementing a GUI toolkit and perhaps it’s just the emergent result of an OOP-based approach (and consequently there are some really brutal tradeoffs in using a widget-based approach for a toolkit). To that point, with respect to general drawing libraries, I don’t think that OOP/inheritance yields a more elegant design than a reactive or intermediate mode approach (perhaps these terms only apply to GUI, but I imagine there are parallel terms for graphical APIs in general). Even though I concede narrowly on the widget GUI library point, these libraries are so very rare that I don’t think it’s a very compelling case for OOP proponents. I suspect they’d like to argue that there are appropriate uses for inheritance in most applications and not just the odd GUI library. Otherwise I don’t think it even merits first-class language support (why bother with an `extends` keyword if it’s only going to be useful in the rarest of libraries?).
- divs1210 5y agoDisagree. See reagent[0]. [0] https://reagent-project.github.io/ https://reagent-project.github.io/
- colllectorof 5y agoAlan Kay spent the last 40 years educating people on OOP and system design. His talks and research papers are now widely available on the internet. There are free, modern and easy-to-use versions of Smalltalk. Anyone who still remains ignorant about fundamental ideas behind classic OOP and the paradigm's history is willfully ignorant.
- throwaway894345 5y agoLots of OOP proponents disagree strongly with Kay’s definition of OOP, and his definition certainly doesn’t reflect the way the most popular self-described OOP languages are written today. Notably, Smalltalk has a negligible share of the market, so why should anyone waste time debating Kay/Smalltalk’s notions of OOP when they are at best niche? Further, and more relevant to the thread at hand: it’s not clear to me that Kay’s notion of OOP considered inheritance to be a critical feature. To quote him: > I felt somewhat the same way about inheritance as I did about types, in that both needed to be a lot better than they were in order to pay for the overheads and pitfalls of using them.
- karmakaze 5y agoI've never heard this brought up before. What's the distinctions? The thing I've noticed and found lacking in modern OOP is that it tends to be class-based without metaclasses or metaprogramming. Is there something else? Static typing is also something that not in Smalltalk, but that shouldn't change the network shape of objects.
- throwaway894345 5y agoHere are some of the definitions I've heard: * OOP is about message passing (where message passing is NOT method invocations) * OOP is about message passing (where message passing can be method invocations) * OOP is about encapsulation (never mind that most/all paradigms make extensive, idiomatic use of encapsulation--some OOP proponents suggest encapsulation implies constructors that do lots of work, take ver few arguments, and make the class virtually untestable, others argue that this is an "abuse" of OOP or "bad programming") * OOP is about inheritance * OOP is a Kingdom-of-nouns programming style (effectively Joe Armstrong's "You wanted a banana but what you got was a gorilla holding the banana and the entire jungle" observation) For all of these definitions, I've heard many OOP proponents argue that these things are not true OOP (typically without rebuke from other OOP proponents in the forum, bizarrely). In my opinion, OOP must be defined by the things that distinguish it from other paradigms. Considering encapsulation and method calls are both fundamental to other paradigms, these cannot be defining characteristics of OOP. Additionally, any defining characteristic of OOP must be shared by languages that are virtually universally recognized as OOP, which means that message passing in a non-method-call sense must be excluded. That generally leaves inheritance, "extreme encapsulation" (untestable constructors), and kingdom-of-nouns programming styles. I don't think the "class-based" thing is meaningful because apart from inheritance there's not much to distinguish a "class" from a struct in Go or Rust (in both cases you can associate methods to the struct for interface polymorphism) which are generally not considered to be "OOP languages" (and Go certainly doesn't have metaclasses or metaprogramming). > Static typing is also something that not in Smalltalk, but that shouldn't change the network shape of objects. I agree that static typing is not a defining characteristic of OOP, and I've never heard anyone argue that it is.
- Ensorceled 5y agoIn my case, I'm using Django on several projects. It uses inheritance to implement the ORM, the views, filters, etc. etc. When you say "there are virtually no valid uses of (implementation) inheritance" ... how do you expect the thousands of us using Django to respond to that? A link to the Django framework? To defend Django? What is the point? You're right, maybe python's object model could have instead been implemented like Go's struct but it wasn't.
- formerly_proven 5y agoIMHO there's quite a difference between what's technically inheritance in an ORM (I am assuming you mean writing "class MyModel(orm.model):", not in-database-inheritance) and Java'esque tree hierarchies of classes. The former is mostly about invoking a type operator / metaclass [1] to construct a model class from your declarative specification. I don't know what the latter is about. I think deep inheritance (where deep means like "more than 2") are virtually always a mistake. Stuff like toolkits that go Object>Widget>AbstractButton>PushButton might be an exception but I'm not entirely sure, there's probably a better way. [1] I think metaclasses aren't type operators in the strict sense, because they're not handed a finished type, but rather the declaration of a type, and then create a type. Maybe there's a word for that.
- throwaway894345 5y agoI don't know enough about Django's API to speak intelligently, but I have 15 years of Python experience and (except when APIs require it) it's perfectly easy to write Python code without using inheritance (and your code base will be better because of it). If Django or whatever requires using inheritance, you have my sympathy, and I'm not arguing that you should go to great lengths to avoid it--I'm arguing that from a language design perspective inheritance is a mistake.
- Ensorceled 5y agoAnd yet here I am being productive.
- 5y ago
- inopinatus 5y agoWell, since you ask, I downvoted you for restating the false equivalence between OOP and inheritance, for the abjectly incorrect (and also, wholly unconstructive) straw-man statement that no-one agrees what OOP is, for the frankly absurd and wilfully ignorant claim that no-one articulates practical examples for the circumstances when inheritance rather than composition might actually be worth considering, and for bitching about downvotes, particularly that explicit assumption that they’re coming from people wedded to inheritance, and not from people who dislike disingenuous arguments and circular reasoning. Read a fucking book, instead. David West’s Object Thinking, for example.
- throwaway894345 5y ago> Well, since you ask, I downvoted you for restating the false equivalence between OOP and inheritance, for the abjectly incorrect statement that no-one agrees what OOP is, for the frankly absurd and wilfully ignorant claim that no-one articulates practical examples for the circumstances when inheritance rather than composition might actually be worth considering, and for bitching about downvotes, particularly the explicit assumption that they’re coming from people wedded to inheritance, and not from people who dislike disingenuous arguments of any form. Read a fucking book. David West’s Object Thinking, for example. Thank you for clarifying that your downvote was definitely not an emotional overreaction. :)
- inopinatus 5y ago> Thank you for clarifying that your downvote was definitely not an emotional overreaction. :) Smileys don’t turn snide into humour, so now you can add “naked ad hominem” to the litany of downvote attractors.
- throwaway894345 5y agoI thought it was the italics. In which ever case, this conversation has definitely been fruitful and enlightening. Thank you for your contributions. . . . . . :)
- AdieuToLogic 5y ago> I’ll go out on a limb and posit that there are virtually no valid uses of (implementation) inheritance. class Iterable { ... } class Tree extends Iterable { ... } class SortedTree extends Tree { ... } class Map extends Iterable { ... } class HashMap extends Map { ... } class InsertionMap extends Map { ... } class BiMap extends Map { ... } Need more examples of "valid uses of (implementation) inheritance"? > And if you get rid of inheritance, there is very little left to distinguish OOP from procedural programming like one would do in C or Go. No. To make OOP indistinguishable from "C or Go", you would also need to eliminate at least; encapsulation, composition, access control, and compiler provided dynamic dispatching.
- throwaway894345 5y ago> Iterable That’s easily achieved with plain interfaces. It’s not obvious to me at all why I would want to use inheritance instead of interfaces, especially because you elided the class bodies. > No. To make OOP indistinguishable from "C or Go", you would also need to eliminate at least; encapsulation, composition, access control, and compiler provided dynamic dispatching. C and Go have all of those things except that C doesn’t have “compiler provided dynamic dispatch” and I’m not sure how “access control” differs from “encapsulation” (access control is just public/private/etc, right?). * encapsulation: in C things in the header files are “public” while things in the c files are “private”. In Go we have private/public struct members. * composition: both C and Go have structs * compiler-provided dynamic dispatching: Go has interfaces and closures. C doesn’t have this provided by the compiler but you can implement them yourself easily enough. You lose out on some type safety, but that’s no worse than a dynamic OOP language and if you care about safety you probably aren’t using C anyway.