I think a similar but perhaps more accurate question is how did we prioritize virtual dispatch over ADTs?
And I think the answer has a lot to do with the expression problem [1] and which kinds of extensibility were needed in the kinds of programs that languages at the time were designed for.
OOP with subtyping and virtual dispatch makes it very easy to define an interface with a set of methods, and then have an open-ended set of concrete classes that all reliably implement those methods. It makes it easy to say "I don't know what data types I'll need yet, but I do know what operations I'll need."
ADTs flip that around. That make it easy to express "I don't know what operations I'll need yet, but I do know what data types I'll need."
For the kinds of simulations that Kristen Nygaard and Bjarne Stroustrup were writing, and then later the large GUI applications that C++ users were building, it seems that the former was more useful than the latter.
And I think the answer has a lot to do with the expression problem [1] and which kinds of extensibility were needed in the kinds of programs that languages at the time were designed for.
OOP with subtyping and virtual dispatch makes it very easy to define an interface with a set of methods, and then have an open-ended set of concrete classes that all reliably implement those methods. It makes it easy to say "I don't know what data types I'll need yet, but I do know what operations I'll need."
ADTs flip that around. That make it easy to express "I don't know what operations I'll need yet, but I do know what data types I'll need."
For the kinds of simulations that Kristen Nygaard and Bjarne Stroustrup were writing, and then later the large GUI applications that C++ users were building, it seems that the former was more useful than the latter.
[1]: https://journal.stuffwithstuff.com/2010/10/01/solving-the-ex...