> traditional gratuitous use of object classes for everything
This sort of phrasing is sort of distressingly characteristic of contemporary discussions about object-oriented programming.
I can understand where it comes from - if you look through my comment history, you'll probably find plenty of examples of me running my mouth about Java or the overuse of OOP in Python - but I assure you there is a baby in all of that bathwater, and it doesn't need to be thrown out. That baby is dynamic dispatch, and it does let you do some things that can be a hassle without it.
Unfortunately, it tends to be poorly taught or poorly understood nowadays. This is not a "no true Scotsman" argument. I'm not saying no true hammer would be used to drive screws. I'm just observing that, if a carpenter was never taught about screwdrivers, it's no surprise they'll develop a lot of pent-up frustration about hammers, and perhaps even be a bit confused about what they're really for. It seemed to me that one of the core sections of the essay ikrubner linked above rested on a conflation of dynamic dispatch and dynamic typing. Which is a worrisome thing I've seen many people do. It's no wonder we don't use OOP well, living in an intellectual environment where its only truly distinguishing characteristic rarely even makes it into lists of its key features. So, perhaps it's even worse than just having only been given a hammer. We were only given a hammer, and were also never taught about nails.
Anyway, enough complaining. Let's take Racket's image drawing library as a positive example. It's implemented around an object-oriented interface. What this does is lets you write code against that interface, so that it is able to output graphics to any format that has a suitable implementation of that interface, without needing any special glue code or explicit branching logic to make it happen. I would argue that this is quite useful.
As a contrasting example, Haskell's typeclasses are superficially quite similar, but, since they use static dispatch, adding a new output format does tend to require some glue code - not much, but still more than zero - that's specific to each drawing routine you want to hook up to that new format.
There's a nice essay, https://www.sicpers.info/2018/03/why-inheritance-never-made-... , that serves as an excellent excoriation of the C++/Java/etc lineage of OOP. But one key thing needed to contextualize it is that OOP mechanisms like Racket's or CLOS aren't trying to do OOP in the same way that Java does, and therefore don't run afoul of the same shortcomings. In particular, they're not trying to turn it into a single golden hammer that solves all abstraction problems. Racket gets a lot more mileage out of its module mechanism, for example.