> I never even mentioned anything that even relates to runtime types, I don't know why you'd bring them up?
You've complained about dynamic overrides. You're talking about dynamic overrides because in the case of "static overrides" (or usually in "normal" OOP languages that are overloads) there can't be any confusion which method gets called. The compiler, and therefore your IDE, knows that. Dynamic overrides are only a thing when dynamic dispatch is involved. Dynamic dispatch is directly related to runtime types.
> And saying that classes, inheritance and overriding are orthogonal is bizarre. They're intricately linked and at the heart of OOP.
That's only the case for languages like C++ / Java and clones.
You can have of course inheritance and overriding without classes. See Self or more prominently JavaScript. (No, JS does not have classes. It has by now some syntax sugar that is called "class", but that's just a simple source translation to JS prototype system under the hood).
> It doesn't even make sense to define overriding without inheritance.
Of course you can have overriding without inheritance.
You can create type-class hierarchies where functions on the leaves override functions above them in the hierarchy.
This is possible without having any inheritance relation between the objects involved. I could show you Scala code that does exactly this.
In a system with prototypes there is also no need for any inheritance relationship to override something. You can just grab the prototype of an object and change ("override") methods on it. You can do that form everywhere in your program in a language like JS…
And in theory you could have inheritance without overriding. Also of course no classes are needed for that. (Even I don't know any language that does something funny like that as it would be quite limiting).
> Coinductive types have destructors so they look a bit OO-ish, but that's it.
No, that's not it.
You can create an algorithm that can translate code form the FP form to the OO form (and back).
I didn't invent this. Someone actually created such an "converter". (I would need to dig a little bit to find the relevant paper and YouTube talks again; maybe you're faster with googling :-D. If not, feel free to ask again, than I would go digging in my PDF chaos).
> The key part of OO isn't having fields, but inheritance.
Well, the inventor of OO himself would strongly disagree… ;-)
OO is about message passing.
The C++ / Java "OOP interpretation" is some quite ill abnormality OTOH.