Why inheritance sucks
ducktypo.blogspot.com
ducktypo.blogspot.com
A snippet consists of functions which accomplish a specific task. The important part is that the entire snippet is a single cpp and a single header. No dependencies.
There are certain programming problems which can be solved once and used forever. The problem wouldn't necessarily be considered a single function. However, it isn't a massive problem either.
My friend solves these problems by creating a single .cpp and a single .h file. The .cpp is the implementation; the .h file defines the interface. He calls this a "snippet".
Now, the power of the snippet is that you can simply copy the .cpp and .h into any C++ project anywhere and it's good to go. There is no tweaking, include'ing, anything. It just works.
This code can then serve you for the rest of your life, regardless of what project you are currently working on. You can say "I've solved that problem before", and be able to spend literally 30 seconds implementing it into your current project, because all you have to do is drag'n'drop two files.
I could imagine some snippets that don't take any dependencies, but they are pretty few and far between. Do you have pointers to some of the more interesting snippets he's posted?
There are surprisingly many useful snippets. For example, a single header and source file for an entire, complete A* pathfinding implementation! That's a massive timesaver.
Cool stuff. Thanks for the link. Although I'd still call them functions. :-)
At the end of the day, they're libraries. Small libraries? Sure, but still libraries.
What I would like to see — at least in Java — is a keyword or annotation for instance fields to mark them as pseudo-superclasses. Then the compiler would generate all of those call-through methods automatically, unless overridden in the current class.
If you find yourself writing a lot of boilerplate code, you're doing something wrong, whether you're using inheritance or not.
Having worked with a lot of C++ code recently that employs both methods, I personally prefer inheritance for the majority of cases. One of my primary goals while writing code is to write as little code as possible. If I have to write wrapper methods to expose the interface of the back-end class I've composed, then I'm not achieving that goal.
Code reuse is the only good reason to use concrete inheritance and there are many situations where concrete inheritance is much cleaner than composition. Honestly, this whole conversation feels a little silly to me.
However, if you just think that some of the functions in AbstractMap are useful but plan on creating a totally different class that doesn't conform to the interface, then inheritance is inappropriate.
Code reuse is not a reason to use inheritance; it is a byproduct of it.
The reason to use interface inheritance is to allow polymorphism in a statically typed language.
The only reason to use implementation inheritance is code reuse. And yes, you should only do that if the classes conform to the LSP.
Despite linking to the Wikipedia, he also does provide the right definition of the diamond problem: <blockquote> This is the dreaded "diamond" problem that C++ programmers learn to fear: if your class has two superclasses that both define an instance variable named x, then you can have a hard time specifying which x you're using. </blocquote> Where is the diamond here?
Object
/ \
A B
\ /
C
Where A and B are parents of the class C. In most OO languages there will be an implied parent of A and B, like Object.That line also bugged me. I struggle to see how that's a good thing. That seems like you could have code breaking in seemingly unrelated code due to seemingly common naming issues. That can't be right, can it?
Although Ruby's "modules" are indeed preferable to inheritance they are usually as inappropriate as inheritance.
To my experience, object composition solves most of the design issues in a more elegant way. And I wonder why this is still so less understood by most programmers. It isn't even particularly new. Even the good old GoF patterns recommend object composition over inheritance, especially in their Smalltalk examples.
(In their book, they demonstrate each pattern in a static (C++) and a dynamic (Smalltalk) language, so Ruby programmers should have a deeper look at the Smalltalk part of the book, rather than imitating the C++ variants of the patterns.)
Composition, on the other hand, is explicit. When you use it, you notice the complexities. That gives you an incentive to simplify your design, which makes you write actually simpler code.
Now I have a problem, however: what is the difference between OO and stateful functional programming?
Speaking for myself, OOP is a way to orchestrate programming on a large scale. To grow software without growing the frequency, severity, and difficulty of bugs and without growing costs associated with new features is the desired result. Component-ized architecture takes great steps to achieve this result. For this reason, I view OOP as being some combination of: message passing, encapsulation, and polymorphism. I do not believe this is a complete view of OOP, nor that there is no viable alternative view of OOP.
Parametric polymorphism ∈ FP
Yes, some statically typed languages like C++ and Java enforce certain inheritance constraints via classes or explicit interfaces before you can use polymorphism.
But almost all dynamically typed languages allow for ad-hoc polymorphism. For instance, in Python this is called "duck typing". Just because two objects provide a "foo()" method doesn't mean they are in any inheritance relation to each other. But polymorphism should still work.
Sometimes people refer to the specific problematic inheritance style as "implementation inheritance". I found it very useful just to know that such a distinction could be made.
Q. What is the object oriented way of getting rich?
A. Inheritance
(its a Friday :))
I have posted a few links about roles to HN. Below are probably best ones:
* http://news.ycombinator.com/item?id=1552691
* http://news.ycombinator.com/item?id=774694
Can't this be said about Java interfaces too?