Inheritance, when used for implementing is-a relationship, is a pretty powerful tool. If you're surprised by overriding, maybe instead of complaining about `Parent parent = new Child()` examples, try to see a `Writer writer = new PdfWriter()`. Are you still surprised that `writer.write(document)` generates a pdf?
There are absolutely horrible ways of designing code in Java, but that can be said about any language.
Interface inheritance, used for polymorphism like in your example, is still considered a good practice and is not really criticized as much (an exception is when it is "abused" for other reasons, like in codebases that have one interface for every class, even without polymorphism).
OOP criticism is often centered around two things: inheritance and state hiding via encapsulation. And this criticism often comes also from programmers that use OOP. And IMO it is pretty fair.
Imagine where we would be if an actually good way of doing type systems had been invented in the 1970s and there was a whole family of languages that followed that approach. Oh wait.
> Java absolutely has "just data", they're mostly used for DTOs and database Entities, with tools like lombok @Data and `records` being some nice mechanisms of implementing them.
The fact that you have to step outside the language with @Data rather proves the point. And while Java now has a "record" keyword, they're still reference types, with turning them into actual values being something that's supposedly coming Real Soon Now for 10+ years.
> Inheritance, when used for implementing is-a relationship, is a pretty powerful tool. If you're surprised by overriding, maybe instead of complaining about `Parent parent = new Child()` examples, try to see a `Writer writer = new PdfWriter()`. Are you still surprised that `writer.write(document)` generates a pdf?
Inheritance is a conflation of 3 useful features (interfaces, composition, and delegation) that's a lot less useful than the sum of its parts. Better languages separate these out properly. (And, credit where it's due, Java made a positive step in normalizing the separation of interfaces from the other parts of inheritance).
> There are absolutely horrible ways of designing code in Java, but that can be said about any language.
That's a cop-out. No language completely eliminates bad code, but there are better and worse languages.
You can trivially write a class with public fields without using lombok, you wont get some cookie cutter logic for hashCode and equals, but often you don't need it and with mutable data you may not even want it.
You'll have to be more specific.
> Inheritance is rarely the answer, but it is more than the sum of its parts, and in the rare case it is needed, you really can’t go around that.
Disagree. If you have the individual parts - interfaces, composition, and delegation - then you can do everything that you can do with inheritance, and you can usually do better since most of the time you only need one or two of the three.
I wonder what fraction of the HN readership gets this joke ...
> People, wake up! It doesn't have to be this way. You've been sold Java's absurd contortions dressed in the emperor's new clothes as the default by universities and big corps for decades.
I think this is a very incorrect characterization. Effective Java was required reading for me in the very late 90s (decades ago). Back then it was even argued favor composition over inheritance [1]. AFAIK you'd have to go back to the 70s or 80s for inheritance to still have a good reputation (and which at the time was certainly better than a GOTO statement). The incidental complexity was later revealed to be quite profound, and a large chunk of "Effective Java" is dedicated to explaining these complexities and why and how to avoid these.
[1] https://blogs.oracle.com/javamagazine/post/java-inheritance-...