I _really_ struggled to not use contrived examples when teaching OOP. It was very hard because you don't really need it until your application becomes non-trivial so I see why all the college classes use cars & trucks or whatever.
I think I ended up going with a Player API with tapes, records, CDs etc. Some could skip, others only fast-forward. I was still unhappy with it, but it was better than most examples.
I like to point folks at writing an IntelliJ plugin. I find that some of the best architected OOP programs become nothing but a collection of plugin interfaces and base classes.
But you really need to understand "is a" vs "has a", not burn your base class, let architecture emerge following the rule of 3, rather than quickly jumping on the wrong abstraction to fight duplication.
Sandi Metz really says it better than I can: https://www.youtube.com/watch?v=8bZh5LMaSmE