Hacker News new | past | comments | ask | show | jobs | submit login
Virtual Structs Part 2: Classes Strike Back (smallcultfollowing.com)
65 points by adamnemecek on May 29, 2015 | hide | past | favorite | 12 comments



One of my favorite long-form blog posts about OOP[1] explains why data type inheritance is generally quite useful, but the entire concept of inheritance has been unfairly maligned because in OOP languages, inheritance of data types is tied to inheritance of function implementations, resulting in the fragile superclass problem, breaking encapsulation, etc. We've thrown the baby out with the bathwater.

[1]http://www.smashcompany.com/technology/object-oriented-progr...


One of the best things Java brought to OOP was the idea of the interface. The idea that we can define the functional shape of the object we need, without defining anything else about it. I rarely find the need to use inheritance over interfaces in Java, especially when thinking in terms of Liskov and proper substitutability. The cases where inheritance is the correct decision is actually very rare, compared to the cases where it's simply a convenient but ill-guided method of passing common data and functions around. As an easy example, the fact that `java.io.OutputStream` is a class instead of an interface. In my opinion, that was a bad decision made purely to provide default implementations of the `write(byte[])` and `write(byte[], int, int)` methods. It would have been better as an interface. I really like where Rust went in this regard with traits, especially the ability to define them external to the type itself.


This wasn't something Java brought to OOP, it was borrowed almost verbatim from Objective C (protocols). You can google your way to Java's designers specifically mentioning this as a direct influence.


Perhaps I should have said "popularized by Java". It's also not something that couldn't have been done in C++ by creating classes which consist purely of abstract functions, since C++ allows for multiple inheritance.


That's probably true, although I'm not sure it's a very meaningful distinction as you can make a fairly reasonable argument that Java popularized OOP in general or at least, put it in the mainstream. I did find the post I was thinking of

http://www.virtualschool.edu/objectivec/influenceOnJava.html

Among other things, it gives a bit of an inkling of the attitudes of the people working on then-current and new OOP systems and languages towards C++ at the time.

But, yes, that sort of thing quickly becomes talmudic interpretation of 'what is true oop' :)


Funny, I think about it the other way: inheritance of function/method implementation is so useful, it's a shame people mentally tie it to data type inheritance.


Functional languages support this view, with powerful features like Haskell's typeclasses and Clojure's protocols and multimethods.

It really boils down to the expression problem. If you imagine a grid of implementations where rows are datatypes and columns are functions, you want to be able to extend the grid with new rows and columns easily (and if you're working in a static language, without recompiling the code representing the other grid cells). OOP languages make it easy to add new rows (types) but more difficult to add new columns (functions) that work on existing types. Functional languages are the other way around. But Haskell's typeclasses and Clojure's protocols (basically forms of function implementation inheritance) make it easy to add rows and columns to your expression grid.

https://www.ibm.com/developerworks/library/j-clojure-protoco...

http://paulkoerbitz.de/posts/Solving-the-Expression-Problem-...


You may want prototype based inheritance like in Javascript/ES6:

http://en.wikipedia.org/wiki/Prototype-based_programming


Prototype-based inheritance seems to be the opposite of what he's arguing for. He's saying it's useful to have data-type hierarchies, but not implementation inheritance.


I don't think so.

"Prototype-based programming is a style of object-oriented programming in which behavior reuse (known as inheritance) is performed via a process of cloning existing objects that serve as prototypes. This model can also be known as prototypal, prototype-oriented, classless, or instance-based programming."

In class based programming you have the fragile base-class problem, as the OP mentioned. Prototype based programming is more powerful and you could emulate class based programming in it (as is done in ES6 with the new "class" syntactic sugar).


I don't see how prototype-based programming solves the fragile base-class problem. Instead you just have the fragile "base-object" problem.


The nice thing about JavaScript is that you have first-class functions that are closures, so you don't have to do OOP at all if you don't want to. And your objects don't have to define methods because you can just define functions outside of methods.

And although JavaScript's prototypes don't solve the fragile base class problem, they do offer a handy solution to the expression problem: http://www.jayway.com/2013/06/21/15201/




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: