7 ms·
If you ever open the hood of a modern car and look around a bit you'll discover that at the front there's a half dozen pullies connected to one or more belts. E
by DubiousPusher 9y ago
If you ever open the hood of a modern car and look around a bit you'll discover that at the front there's a half dozen pullies connected to one or more belts. Each of these pullies is connected to some diffeerent system each able to turn rotational acceleration into a useful service. The alternator converts that rotational energy into electricity. The AC unit uses it to operate a heat pump. The coolant and oil pumps use it to circulate fluid. In the past, these parts were sometimes driven by another system or integrated directly into another part. But over time, as a convenience to many different parties it was decided they should all implement a pully and connect dirctly to one of the main belts that connect directly to the motor. Not a single one of these parts has anything you'd call a taxonomical relationship. They do have an invented one. And it is as much about conveniencing the overall system design as much as conveniencing the individual part design. They are all "pully implementers" subscribed to the "belt druve" system.
This is the inheritence I find most powerful in software. These things aren't the same but if we treat them the same, the downstream and upstream code are simpler, easier to replace and consistent. I don't worry too much about the philisophical relationship between the objects.
- dyarosla 9y agoYou’ve described interfaces, not so much inheritance.
- kbsletten 9y agoIn 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.
- humanrebar 9y agoThere are at least a few ways to define and implement interfaces in C++ without touching inheritance.
- andrewflnr 9y agoStructures 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...
- nostrademons 9y agoTemplates 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.
- stephen_gareth 9y agoIn 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++. https://www.youtube.com/watch?v=bIhUE5uUFOA https://www.youtube.com/watch?v=bIhUE5uUFOA
- dwaltrip 9y agoCan you give a mechanical example of inheritance, so we can see the difference?
- baddox 9y agoI 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.
- weberc2 9y agoYou'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).
- baddox 9y agoI’m not confusing those things. I’m giving an example of an interface, as requested.
- deleted 9y ago[deleted]
- dllthomas 9y agoIt may have been edited, but at least presently the comment you replied to asks for an example of inheritance.
- baddox 9y agoOh 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.
- sametmax 9y agoInheritance does allow you to avoid implementing part of the interface.
- eikenberry 9y agoWhat you are describing is an interface, not inheritance. They are implementing an pulley interface, not inheriting a specific pulley implementation from a common housing or something.
- bunderbunder 9y agoThe distinction between "implementing" an interface and "inheriting" a base class is largely just a Java-ism. To some extent, it's a distinction without a difference - at a semantic level, Java only distinguishes between interfaces and purely abstract base classes because one allows multiple inheritance and the other doesn't, and the separate "inherits" and "implements" keywords flow from there. Other languages (like C# and Kotlin) distinguish between interfaces and overridable classes for the purposes of deciding when to allow multiple inheritance, but use the same syntax and terminology for inheriting from both interfaces and base classes. Still other languages make no structural distinction, but still use the word "interface" to refer to base classes that don't include any implementation, and therefore aren't so susceptible to the diamond inheritance problem. TBH, I think the Java-style treatment is the least conceptually consistent, since it's entirely possible to "inherit" a base class without inheriting a single bit of information, either because everything it declares is abstract or because everything got overridden. There's a pretty decent coverage of all the grotty details of this concept space, and how different languages treat it, in the beginning of the gang of four book.
- DubiousPusher 9y agoThank you. I came up in C++ land where the distinction between interfaces, abstract classes, and base classes is pretty muddy.
- legulere 9y agoI kind of like interfaces as they are basically less powerful traits. I think there is a big difference to class inheritance and the difference between e.g. Jave and C# is just syntactic. When you implement interfaces you have to explicitly implement all methods. If you implement them correctly all methods using them continue to stay correct (including C# extension methods or java interface default methods). With class inheritance you have two large problems: you also inherit state that you might not need, might not have access too and might change in future versions of your base class. Secondly you might need to override methods of the base class to provide correctness. If your base class adds/changes methods your subclass can easily behave wrongly.
- donatj 9y agoWhich is also why these modern cars have turned a minor belt failure into an expensive catastrophic failure, often destroying much of the engine. I'd hardly call it a design to aspire to. I'd probably compare it more closely with a system where everything receives a mutable God object.
- guiscreenshots 9y agoHe's describing the accessory belt. You're referring to the timing belt.
- LifeLiverTransp 9y agoThis description and definition discussion describes very well the definition lawyering and specsheet-rewritting that agile avoids, by having the walking specsheet (customer) sitting in during the creation process.
- DubiousPusher 9y agoYes, the timing belt or timing chain is inside the engine casing and it can be bad when it or subordinate parts fail. Though a timing belt/chain failure causing a catastrophic event for the engine itself, I don't think that's very common. What I'm referring to is called the serpentine belt and is often accompanied by what's called an accessory or AC belt.
- sametmax 9y agoBut modern cars don't need nearly as much maintenance and are more reliable on averable.
- donatj 9y agoThat has not been my experience at all. My 91 pickup and 99 minivan's engines are still going strong with well over 200k miles, rarely having anything major wrong with them in the entire time I own them, whereas my 2004 and 2009 cars both with ~100k miles have been nothing but total maintenance nightmares. Timing issues, computer failures. Sheer nightmares.