A graphics driver for a certain vendor inherits from the DRM class, which inherits from PCI, which inherits from the Device class. Structs which embeds structs which embed structs, and you can access the base classes using the container_of() macro.
As for me, I particularly abuse inheritance in C++, although I a lot of cases I end up replacing it with template programming. To the luck of society, most of the code where I abuse templates and inheritance is not used by anybody else except for me.
Flat is better than nested.
When there's a good reason to use it, use it. If there's not, don't. Nobody's forcing you to use it.
I think inheritance is a bad solution to the problem of wanting to call foo's baz() method or access a property. Been way long since I poked at Ruby or Javascript but I thought those languages allow you to do that without inheritance. If so why would you even bother 99.9% of the time.
Never ever do I do this for tables / entities or controllers. Things get fragile fast with that.
Larger codebases also use them extensively. I worked on a project which had multi-millions in funding. Basically it was video streaming functionality, dealt with DRM/CA, rewind, optimization, all that done. We were on the UI team, meaning we build a different UI based for a specific client brand, utilizing the same code as in done in many countries.
With those, you don't build a custom code from scratch. You just inherit and modify.
I only use them heavily in Java though, never JavaScript, even though we built that video streaming app in both. It's just a different paradigm. I can live fine without inheritance though. It's just a nice to have.
I also remembered that unit test suites are an instance when I've enjoyed inheritance.
But it sounds like most people here do not use inheritance in the business logic of their apps/systems. Composition and dependency injection do the job of sharing code without sacrificing comprehensibility.
Thanks everyone! This all matches my experience as well. I just wanted to make sure I wasn't missing something life-changing!
shape
...
circle extends shape
I find it very useful to extend classes in an existing framework or system with a new functionality specific for my particular problem.For a general example, sub-typing exceptions is useful.
I would say that having a multi-level inheritance hierarchy with greater than "constant" number of children per parent in one package is a code smell.
I’ve found the best way to add some extra view data to a class that is directly backed from a DB table is to inherit from the 1-1 class that Dapper uses, and just add the extra data in the child class.
That way dapper doesn’t get confused by properties not mapped to the database table, but I get to use the extra data properties in my view.
Though sometimes I'll have an inheritance tree of interfaces, which is pretty easy to manage.
The best way I've found to share behaviour is dependency injection, it's more flexible and consistent than shared methods in a parent class. But you need a DI framework to manage all the instantiation, which can add undesired complexity.
When I teach inheritance to students, it’s not usually with the mindset that “You’ll use inheritance a lot in the original code you write.” The mindset I teach with is, “You’ll see inheritance often in the codebases you work with.”
The only times in recent memory where I have inherited a concrete class from another concrete class was to add functionality to an existing program without starting a massive refactor.
In other words can you freely swap out derived classes you didn’t know about when you wrote the base class.