TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Why general inheritance is flawed and how to finally fix it

99 pointsby gulbrandrover 3 years ago

17 comments

armchairhackerover 3 years ago
I think that composition is absolutely better than inheritance except for one thing: boilerplate. The issue is that boilerplate is kind of important.<p>You don&#x27;t want to litter your code with &quot;f150.ford.car.vehicle.object.move(50, 50)&quot;. You can and should re-implement &quot;move&quot; so that you only have to call &quot;f150.move(50, 50)&quot;, but that still requires boilerplate, just in the &quot;F150&quot; class.<p>Often you have class containing all of the functionality of another class, except a bit more functionality. You can always use composition but this happens so often you&#x27;re creating a lot of boilerplate.<p>You could develop some other &quot;syntax sugar&quot; to replace inheritance. Maybe Haskell&#x27;s type-classes are better (although they also kind of use inheritance, since there are subclasses). But chances are you&#x27;ll go back to something like inheritance, because it&#x27;s very useful very often.
评论 #29537578 未加载
评论 #29535158 未加载
评论 #29538514 未加载
评论 #29539070 未加载
评论 #29535476 未加载
评论 #29536174 未加载
评论 #29538175 未加载
评论 #29534767 未加载
评论 #29563764 未加载
评论 #29534759 未加载
nickm12over 3 years ago
<a href="https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;548560&#x2F;" rel="nofollow">https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;548560&#x2F;</a><p>I really enjoyed the article above, which I read many years ago (before Rust 1.0!) which discusses how Golang and Rust handle polymorphism and code-reuse without classic object inheritance. My current thinking is that software objects are a general-purpose tool, but classic object inheritance should rarely be used as it is a solution to a narrow problem—classes should be &quot;final&quot; by default, and if not the inheritance pattern should be completely designed up front.<p>Java had the misfortune to be designed at a time when OOP was the new craze and the design decision to force all code into an object hierarchy has not held up well. I&#x27;d rather use languages designed either before or after Java, where you can use objects when they are appropriate and ignore them when they aren&#x27;t.
评论 #29537437 未加载
评论 #29537032 未加载
nauticacomover 3 years ago
I (happily) write a lot of OOP code, &quot;inheritance is bad, use composition&quot; is such a trite and unhelpful dogma that gets in the way of any actual discussion about where inheritance is useful.<p>IMO, the case where inheritance makes the most sense is when you have a set of objects polymorphically answering some question, usually with a <i>simple</i> answer.<p><pre><code> class Subset class Whole &lt; Subset def of(items) items end end class Range &lt; Subset def initialize(from:, to:) @from = from @to = to end def of(items) items[@from:@to] end end end </code></pre> which is used as such:<p><pre><code> subset = Subset::Whole.new puts subset.of([&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]) # =&gt; [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;] subset = Subset::Range.new(from: 0, to: 1) puts subset.of([&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]) # =&gt; [&quot;a&quot;] </code></pre> You can then pass around a Subset object anywhere (aka dependency injection) and push conditionals up the stack as far as possible.<p>Simply saying &quot;inheritance is bad&quot; gets nobody anywhere.
评论 #29534857 未加载
评论 #29535069 未加载
评论 #29537900 未加载
评论 #29538882 未加载
评论 #29538796 未加载
评论 #29537997 未加载
zinxqover 3 years ago
The term &quot;general inheritance&quot; was not familiar to me as &quot;inheritance across package structures&quot;. However, my OOP design intuition feels pretty good about that idea.<p>This quickly devolves into the inheritance vs. composition argument which isn&#x27;t where I thought the Author wanted to go (but then sort of ended up going there). I agree with other commenters that it&#x27;s an overstated idea. Inheritance is ridiculously useful in the right design structure, as is Composition. They both have a place. (Incidentally, bad Inheritance design usually looks very ugly very fast - bad Composition is often less glaring).<p>I find that years of designing in OOP has led me to build designs that have a goal of preventing me from making future mistakes <i>and</i> correctly consider implications of my code.<p>I find that my most immediate designs tend me towards Abstract Classes and Interfaces. While I usually get credit for &quot;programming to the Interface&quot; for this, that&#x27;s not what usually led me there.<p>I like abstract methods. They (i.e. the compiler will) FORCE me to think about something if I ever decide to create another subclass of the Abstract class. The Author points out the &quot;forget to call super&quot; bug which is particularly nefarious and I avoid it at all costs. I can do that by providing a final concrete method which calls the abstract method. Let the subclasses implement that and never worry about super.<p>Anyway - governing inheritance across package hierarchies seems like a reasonable guideline. As for Inheritance vs. Composition, I don&#x27;t favor either. When designing a class structure, I just make my best guess (as we&#x27;d all do) and find the structure quickly evolves on it&#x27;s own. Usually, this ends up in a blend of shallow Inheritance trees with logical composition. There&#x27;s always multiple Class Structures that will work - my goal is to find a reasonable one of those.
评论 #29539413 未加载
ncmncmover 3 years ago
Inheritance is flawed, in Java, mainly because it is the only organizing principle offered, so gets shoehorned into all kinds of problems where it is a poor fit.<p>Inheritance is just the right thing once in a while, but Java coders are obliged to apply it well beyond its useful range.
评论 #29537737 未加载
评论 #29538737 未加载
AmericanBlarneyover 3 years ago
The argument is &quot;because it&#x27;s possible to do misuse with inheritance, you should never use it&quot;.<p>By extension then, because it&#x27;s possible to misuse Java&#x2F;any programming language&#x2F;computers&#x2F;electricity&#x2F;etc., you should never use it.
stevenaloweover 3 years ago
Or you could learn to use it properly.<p>Make no mistake, designing classes to support inheritance is much harder than just declaring everything final, and in many scenarios there is no good reason to do so
评论 #29537927 未加载
评论 #29538656 未加载
BlackFlyover 3 years ago
The final keyword is one of those places where Java shows its age to me. I agree with the overall point that inheritance is flawed, but I cannot bring myself to conclude that the use of final is the answer to the problem.<p>Simple example, String is final in Java. It is also immutable, and that is (mostly) irrelevant. Lots of string fields on inbound requests have validations, a simple one would be a field that contains a fixed length string. So obviously you validate that at the ingress before passing it down. Now, the question arises, should the core library be defensive and re-validate the string? Why not simply capture the subtype, TenCharacterString and parameterize methods with that?<p>Modern languages get this right. Subtyping is not inheritance. Inheritance is not subtyping. I should be able to subtype at zero cost, I don&#x27;t need inheritance to do that, [and encapsulation is definitely not subtyping].<p>But Java doesn&#x27;t have that. You mark something as final and you lose the ability to subtype just to eliminate the possibility of inheritance. On the other hand, to be fair to the argument against final, the real answer to my complaint is a proper type aliasing support.
评论 #29538065 未加载
smarksover 3 years ago
The author is onto something but I’m afraid it’s not explained very well. I think he’s mostly right though.<p>While reading it I was reminded of a design&#x2F;implementation style I’ve run across several times over the years which is to find an existing class that does something similar to what you want. Then, subclass it and override methods until you get the behavior you want. And you’re done!<p>This leads directly to the Fragile Base Class problem. I think it also violates the Open&#x2F;Closed principle. When subclassing occurs across components that are released independently (e.g., a library and an application), it either leads to continual breakage at each release, or ossification of the library. The latter happened to Java’s Swing. It got to the point where it was difficult to fix any bugs, because any “fix” would end up breaking some subclass that relied on the old behavior.<p>(See also Hyrum’s Law, which is more general than subclassing &amp; inheritance.)
评论 #29537788 未加载
taericover 3 years ago
I feel the flaw is in building ontologies. Satic ones, at that.<p>There is great value in reducing type errors at runtime. Is hilariously ironic that one of the main tools we reach for seems intent on just moving them to design time.<p>Notably, not compile time. Design. Most failures from mistakes in ontology stall the problem out before release.<p>(Obviously, ymmv.)
tabtabover 3 years ago
The real world rarely sticks with nice hierarchies. Variations of set theory is more powerful, but would generally require merging RDBMS with IDE&#x27;s, which does deserve more R&amp;D. Using code to manage complex sets is limiting; query languages do it smoother because that&#x27;s what they were intended for.<p>I&#x27;ve experimented myself with &quot;table oriented programming&quot;, but don&#x27;t have time to explore all the leads I uncover and rework the problem areas. Maybe when I retire?<p>For example, modern CRUD stacks are really just &quot;event handling databases&quot; done poorly. An RDBMS would be better at managing the gazillion event snippets, if it could &quot;talk to&quot; the compiler properly.<p>The &quot;do everything in code&quot; mantra of the web era is a mistake. Databases are better at managing complex relationships and masses of field&#x2F;UI attributes, code better at non-collection-oriented algorithms. We should use the right tool for the job. &quot;Data annotations&quot; in Java and C# look like JCL&#x27;s mutant stepdaughter. If that&#x27;s the pinnacle of CRUD, then slap me silly.
评论 #29581509 未加载
cpcallenover 3 years ago
I got the same feeling reading this article that I got from reading _Design Patterns_: that the author(s) present some useful techniques to deal with the shortcomings of Java, but that most of their recommendations seem like kludgy fixes to problems that are absent or at least much less severe in better-designed languages.<p>I also note that, while the author does make some useful points about how to program more defensively, especially in the face of unexpected modifications to super&#x2F;sub classes written by other programmers, one is inevitably beholden to at least a certain extent on the trustworthiness of code that one depends upon. (Even languages like LambdaMoo that start from the assumption that a program consists of code written by multiple mutually-untrusting programmers cannot entirely protect each against malicious subterfuge by the others.) I therefore question the value of the kind of &#x27;hardening&#x27; the author recommends, especially when it might have unfortunate consequences on extensibility and testability.
评论 #29540277 未加载
jqpabc123over 3 years ago
Spaghetti code, spaghetti objects.<p>Same stuff in a new way.
menotyouover 3 years ago
I am always astonished&#x2F;shocked&#x2F;surprised how many articles are written trying to solve obscure problems&#x2F;work arounds resulting from using OOP.<p>How about considering if OOP might be a stupid idea at the first place?
toolsliveover 3 years ago
There are also problems with the combination of inheritance and concurrency. Google for &quot;inheritance anomaly&quot;.
评论 #29537717 未加载
al2o3crover 3 years ago
Re: using composition<p><pre><code> In the past, it was feared that this would lead to reduced performance but this is simply not the case. </code></pre> Great to see the strong evidence here &#x2F;s
评论 #29534920 未加载
评论 #29535700 未加载
评论 #29535359 未加载
echelonover 3 years ago
Fantastic article!<p>Object oriented programming gets a horrible wrap on the basis of inheritance alone, and it&#x27;s no wonder. Outside of limited domains, such as GUI programming, object inheritance makes little sense. Computer science students are right to question their introductory classes on inheritance when they teach contrived examples of dogs barking and cats meowing as an example of Mammal.makeSound() inheritance.<p>It&#x27;s almost as if we&#x27;re shoehorning in a code dispatch framework as a major language feature, except that framework sucks and we&#x27;re stuck building with it. The best strategy working in languages with inheritance is to avoid it.<p>Duck typing or traits are better ways to represent polymorphic behaviors. We&#x27;ve known this for over a decade now.<p>Here&#x27;s hoping that no new languages come with object inheritance as a concept. It&#x27;s deader than NULL and shouldn&#x27;t be resurrected.
评论 #29537843 未加载
评论 #29539830 未加载
评论 #29544124 未加载