In the language of the article, this is subtyping without subclassing. Sure Java/C# implement this as interfaces, but in C++ this would be a case of multiple inheritance. This is a good example of the article's main point that people mean a lot of different things by inheritance and get different value from the different applications of the concept.
Structures of function pointers and, what, string method names? My C++ is rusty, but that's all I can think of. I guess there's a lot of variations on structures of pointers...
Templates and compile-time polymorphism. This is what the STL is based upon. A forward iterator is any type for which the * and ++ operators are defined; you can use it in any template that makes use of just those syntactic forms, but will get a compiler error if you try to instantiate a template with a type that does not support those operators.
Punning on memory layouts, a la PyObject_HEAD or some of the objects in V8. With this approach, you make sure that all related types have the same memory layout for a subset of fields at the beginning of the struct. Then, a reinterpret_cast on a pointer to one member of the type will yield the same values as a different member of the type, and so can be used generically by code that depends only upon those members. (You have to be very careful with this approach, because multiple inheritance and vtables will usually break it, but if you absolutely positively must have zero-overhead runtime polymorphism it's occasionally the best option.)
#include and preprocessor magic to redefine symbols based on preprocessor defines. Used to be the old way to swap out different implementations of a cross-platform interface, but seems to have largely fallen out of favor in the last couple decades.
Linker magic to accomplish the same, where the header file defines a common interface but the linker may link with one of several different object files to implement that interface at link time. This one is still fairly commonly used; Google and Facebook both have their own custom STL & libstdc++ implementations, and this is also commonly used to swap out eg. malloc implementations.
dlopen & dlsym to do this at runtime. Header file defines the interface, dlsym gives you back a function pointer or set thereof for a plugin implementation.
In Sean Parent's 'Inheritance is the base class of evil' talk Sean outlines an interesting way to achieve runtime polymorphism without inheriting interfaces in C++.
I think the term “interface” is used in many related but different ways in software, but I think the most obvious mechanical analogy would be basically anything that uses a common “plug” or “adapter.” Like a vacuum cleaner with different attachments. Or even HDMI for video/audio.
You're confusing inheritance with implementing an interface. I'm not sure there is an example in the real world, because the real world is concerned with function, not taxonomy. It hardly makes sense to say "cordless drill inherits from screw driver"; rather, they both implement the "drives screw" interface. Ontological inheritance really doesn't make any sense at all for modeling systems (sometimes ontologies are useful as data in a system, but probably never for modeling the system itself).
They wanted an example of inheritance. Something like:
You need an office. You could create a new office from scratch, or you could also just put a desk in a room in your house and give it a unique address like "Suite 1". Now it's both a Room and a HomeOffice.
But if your HomeOffice exposes a method BuildWall(), which mutates the office into a collection of two Rooms, then it would stop fitting the definition of a Room after calling that method.
I don't know if there are different tax consequences for one-room vs. multi-room home offices, but that's one area where the distinction could at least conceivably be significant enough to affect whether you'd prefer to build a separate office or inherit the old room, or maybe just rent an existing office from a third party.
Oh rats, my mistake. It is harder to come up with s good example of mechanical inheritance. Something like the cassette tape adapter kinda feels like inheritance, in the sense that it can be substituted in for a normal cassette tape but provides its own unique functionality.
Yes, I'm struggling to think of a good mechanical example of inheritance as code reuse.
But I don't agree with the "that's an interface, not inheritance" argument. Well designed super classes tend to provide an interface - they just don't use the "interface" keyword.
If you declare a method as abstract, you're defining an interface that subclasses use to define new behaviour. You see this all the time. If a method is defined as protected, you're saying "I'm allowing subclasses to use this interface to change behaviour".
For example, test frameworks usually provide an overridable method that's run before each test - setUp. That's interface - "I will call setUp before every test - feel free to override it".
To me, that's where shit gets hard. It has to have a well defined interface, it has to be an is-a relationship and it has to be a subtype (Liskov). That's why we see composition over inheritance because it's far simpler to just drop one of the constraints and get decent work done.