News for hackers. Stuff that matters.
Re:Inheritance Is Terrible by danso on Saturday March 19, 2016 @05:06PM (#11320448)
A little OT...but does anyone have insight into the historical reasons of why inheritance seems to be the default entry point into teaching/explaining OOP and classes? I remember learning all about inheritance in school but only tangentially about interfaces. And looking at explainers/tutorials in the wild, it seems that many/most start out with the classic Duck > Animal or Thing > Car examples.

I want to chalk it up to inheritance being an inherently easier thing to think about in real world terms, with a name that has easily-understandable connotations, even if some of those connotations are probably harmful in the way they muddle up via leaky abstraction when thinking computationally. Whereas with mixins/interfaces...those terms have never made immediate sense to me.

And yet when it comes to implementing OOP, mixins/interfaces seem so profoundly more suitable as the go-to strategy that I wish I had learned exclusively about them, with inheritance being left for edge cases. Maybe I just had a bad curriculum or bad memory when it came to the lessons about interfaces. But if there is a stronger focus on inheritance when it comes to teaching OOP, is it due to the design of C++/Java? Or just the practicalities of teaching OOP? Teaching about classes seems like a good first step in teaching OOP, and teaching about inheritance requires fewer new concepts/syntax from defining a class. Whereas mixins/interfaces require introducing the concepts of modules.

Re:Inheritance Is Terrible by putzdown on Saturday March 19, 2016 @05:50PM (#11320644)
Interface relationships are a subset of inheritance relationships. If you understand inheritance you understand interfaces. So it makes sense to explain inheritance before understanding interfaces.

There's an analogy here between inheritance -> interfaces and pointers -> object references as in a language like Java. Object references are pointers, in effect, but syntactically pared down so that it's (much) harder to break them. They are less powerful but safer. Similarly, if you have inheritance—particularly the dreaded multiple inheritance—you have everything interfaces can do and then some, but you also have much more responsibility and a lot greater chance of creating bad designs. In both cases, it makes sense when teaching the concepts to teach the fuller, more powerful concept. In day to day work, however, many programmers will make fewer mistakes using the more limited concept.

To say this a bit more clearly, but perhaps more insultingly: inheritance, properly and fully understood, is useful for a massive range of situations, of which mixins and interfaces are a part. I find that relatively few programmers (and I've worked in development for more than twenty years and taught programming at the Master's level for 7: I've taught a lot of programmers) can really grok proper inheritance to this level; therefore when they try to use it they end up shooting themselves in the foot, then blaming the tool. For them it's better to use the more limited tool. But it's still good to know the broader tool.

Re:Inheritance Is Terrible by parenthephobia on Saturday March 19, 2016 @05:28PM (#11320548)
C++ doesn't have interfaces, so it's quite understandable you wouldn't learn about them if you were learning about C++.

Java-as-taught is often ancient Java, from before enhancements like default interface methods. The only non-annoying way to inherit behaviour in ancient Java is inheritance. Even modern Java lacks automatic implicit composition ala Go.

Java also encourages large interfaces with many methods. Without any ability to inherit behaviour for those methods, it's often less tiresome to inherit from a class instead. Go, by way of contrast, encourages tiny interfaces with, ideally, one or two methods.

In this example, we might suppose that a quintessential "vintage" Java-esque design wouldn't have a single-method "Priceable" interface. It'd have a CartItem interface with hundreds of methods, all of which you'd have to implement - even if only to stub out with exceptions - in order to implement it. So you wouldn't actually use an interface, or else you wouldn't be avoiding all that typing.

Re:Inheritance Is Terrible by neukoelln on Saturday March 19, 2016 @05:43PM (#11320607)
C++ doesn't have the interface keyword, but that does not mean you cannot have a class that is a pure interface (all methods abstract).
Re:Inheritance Is Terrible by parenthephobia on Saturday March 19, 2016 @06:58PM (#11320877)
C++ doesn't have the interface keyword, but it also doesn't have interfaces.

An interface isn't simply a class whose methods are all abstract. It is a distinct kind of type which has no precise analogue in C++ because the language constraints which enable it to exist don't apply in C++. Namely, C++ has multiple inheritance.

To abuse a car analogy, this situation is akin to asking why older drivers weren't taught to use cruise control, and the answer being that many older cars don't have cruise control. Whilst it's possible to "emulate" cruise control by simply maintaining constant speed manually, learning to do that isn't the same as learning how to use cruise control.

Re:Inheritance Is Terrible by neukoelln on Sunday March 20, 2016 @04:14AM (#11322224)
Can you tell me what's the problem with multiple inheritance if your superclasses only consist of pure virtual functions?

From [1]:

"Bjarne Stroustrup: I had a lot of problems explaining that to people and never quite understood why it was hard to understand. From the first days of C++, there were classes with data and classes without data. The emphasis in the old days was building up from a root with stuff in it, but there were always abstract base classes. In the mid to late eighties, they were commonly called ABCs (Abstract Base Classes): classes that consisted only of virtual functions. In 1987, I supported pure interfaces directly in C++ by saying a class is abstract if it has a pure virtual function, which is a function that must be overridden. Since then I have consistently pointed out that one of the major ways of writing classes in C++ is without any state, that is, just an interface.

From a C++ view there's no difference between an abstract class and an interface. Sometimes we use the phrase "pure abstract class," meaning a class that exclusively has pure virtual functions (and no data). It is the most common kind of abstract class. When I tried to explain this I found I couldn't effectively get the idea across until I introduced direct language support in the form of pure virtual functions. Since people could put data in the base classes, they sort of felt obliged to do so. People built the classic brittle base classes and got the classic brittle base class problems, and I couldn't understand why people were doing it. When I tried to teach the idea with abstract base classes directly supported in C++, I had more luck, but many people still didn't get it. I think it was a major failure in education on my part. I didn't imagine the problem well. That actually matches some of the early failures of the Simula community to get crucial new ideas across. Some new ideas are hard to get across, and part of the problem is a lot of people don't want to learn something genuinly new. They think they know the answer. And once we think we know the answer, it's very hard to learn something new. Abstract classes were described, with several examples, in The C++ Programming Language, Second Edition, in 1991, but unfortunately not used systematically throughout the book. "

[1] http://www.artima.com/intv/modern.html

Re:Inheritance Is Terrible by manyxcxi on Saturday March 19, 2016 @05:42PM (#11320605)
I think you're spot on with the lack of a default method in olden days Java. It was certainly the driver behind having an AbstractBaseWhatever class back when. Though there could still be utility in having a base class that had some functionality acting on internal state that was shared by lots of implementations of that.

Another use like Priceable and CartItem in modern Java is Connection and AutoCloseable (database connection objects). Anything AutoCloseble can be automatically closed after a try/catch block is done (with some specifics I glossed over on how). And a Connection is that, some specific form of DB connection. You also have a DB ResultSet that is AutoCloseable. So by having another interface extending another, or a class implementing the interfaces you can drive very related functionality on classes that may do very different things.

CartItem could extend/implement the one or two method Priceable, along with all its other methods.

Re:Inheritance Is Terrible by santaclaus on Saturday March 19, 2016 @05:44PM (#11320612)
> C++ doesn't have interfaces

Isn't a class with exclusively pure virtual methods effectively an interface?

Re:Inheritance Is Terrible by rbehrends on Saturday March 19, 2016 @06:35PM (#11320804)
> A little OT...but does anyone have insight into the historical reasons of why inheritance seems to be the default entry point into teaching/explaining OOP and classes?

Meyer's OOSC doesn't. It explains inheritance 1/3 through the book, after generics (parametric polymorphism) and Design by Contract. Incidentally, OOSC has this paragraph about inheritance that is worth remembering:

"Neither the Open-Closed principle nor redefinition in inheritance is a way to address design flaws, let alone bugs. If there is something wrong with a module, you should fix it — not leave the original as it is and try to correct the problem in a derived module. (The only potential exception to this rule is the case of flawed software which you are not at liberty to modify.) The Open-Closed principle and associated techniques are intended for the adaptation of healthy modules: modules that, although they may not suffice for some new uses, meet their own well-defined requirements, to the satisfaction of their own clients."

(Emphasis in the original.)

The Item class is not an example of a healthy module. It has been written in an ad-hoc fashion, without concerns about its requirements or thoughts about what contracts it should offer to its clients (i.e. how it interacts with other modules). Unsurprisingly, adapting it through inheritance results in breakage.

Re:Inheritance Is Terrible by manyxcxi on Saturday March 19, 2016 @05:26PM (#11320535)
I'm hazarding a guess- I've never looked into the teaching of CS, just been taught a lot of it.

I think it's because people just starting out are able to grasp the concept of a duck is a bird is an animal AND you can reduce the code you write by saying all animals walk, birds fly, and ducks quack. So you are building on from the parent class.

With interfaces you are saying all implementations of animals walking can be different, so you're going to have to write code for each one to this contract. You're not nexessarily suggesting that you could reduce the code you write in that case. Then when you get to all other sorts of class composition it gets pretty hard to understand at first.

I think that's the main reason, it's easier to get started with. Also, CS teaching is nothing like real life development, as you stated, interfaces get used quite a bit more than the idea of concrete, or even abstract base classes but you just might have an abstract base class that implements part of the interface.

Re:Inheritance Is Terrible by ta0967 on Saturday March 19, 2016 @05:43PM (#11320609)
platypus. that is to say: the teaching is still bad.
Re:Inheritance Is Terrible by manyxcxi on Saturday March 19, 2016 @05:55PM (#11320666)
Exactly why I kept going back to- it's easier. By the time they get to platypus they're hopefully in the real world having picked up some of the additional knowledge required to solve it in an elegant fashion.