Sorry I don't think your response really gets to the point. I'm aware of various techniques like contracts, but you're speaking in generalities rather than specifics. So yes, I haven't quite understood what you meant.
This is a common frustration I have with OOP discourse, it tends to be really up-in-the-air and not grounded in concrete specifics. (The article you linked also has this issue.) Meanwhile, users suffer in ways that just don't happen with typeclass-based polymorphism, and none of this discourse is required in my world. So why should I not recommend everyone use typeclass-based polymorphism?
> I am not sure that you understood what i wrote. Inheritance's flexibility is its very strength
No, being too flexible is a weakness, not a strength. At scale, rigorous discipline enforced by tooling is required.
> Also no amount of Automation/Tooling/etc. can substitute for documentation explaining the intent behind the code.
Yes, of course documentation is required. What I'm saying is that if it can be automated, it should be, and that relying on documentation alone is foolish.
In particular, invariants like "no downcalls" or "no upcalls" should 100% be enforced by automation. Documentation is not enough at scale and under pressure.
> i suggest creating a sample MFC app using Visual Studio C++ wizard
I'd rather not?
> The framework invokes your derived methods (i.e. downcall) which can as needed call back to base's method (i.e. upcall).
This sounds really bad to me at scale and under pressure.
I pointed you to a specific book i.e. OOSC2 and three specific chapters in it (to start with) which explain the concepts well with examples you asked for. How much more specific can one get? If you already know contracts then it should be easy to translate the concepts to any language of your choice. Meyer provides a thorough rationale and is extremely detailed in his examples. Furthermore, i also pointed you to one of the largest and commercially most successful class library and application framework (i.e. MFC) where you can see classic OOD/OOP (including upcalls/downcalls) in action; and yet you say i am "speaking in generalities"! It seems you are not willing to read/study but expect a couple of paragraphs to enlighten everything, which is not going to happen.
Eg: Base.method() has {pre1} and {post1} as contracts. Derived.method() has {pre2} and {post2} as contracts. What should be the relationship between {pre2}&{pre1} and {post2}&{post1} to enforce proper subtyping?
> This is a common frustration I have with OOP discourse, it tends to be really up-in-the-air and not grounded in concrete specifics
It is not up-in-the-air when ideas and specific books by authors like Bertrand Meyer and Barbara Liskov (both researchers and practitioners) are being pointed out. Trying to simplify their concepts into a couple of paragraphs would invariably miss important nuances and lead to misinterpretations (the bane of most HN discussions based on trivial articles/blog posts). Hence it is better they are studied directly and then we can have a discussion if you would like.
> Meanwhile, users suffer in ways that just don't happen with typeclass-based polymorphism, and none of this discourse is required in my world. So why should I not recommend everyone use typeclass-based polymorphism?
Sure, there are other types of polymorphisms which can be better in certain scenarios. But that is not under discussion here; we are talking about "traditional" dynamic runtime dispatch based polymorphism which is far easier to understand and implement even in small languages like C.
> No, being too flexible is a weakness, not a strength. At scale, rigorous discipline enforced by tooling is required.
Flexibility increases your "design space" and hence never a weakness. Rigorous discipline is needed throughout development but tooling can only do so much.
> In particular, invariants like "no downcalls" or "no upcalls" should 100% be enforced by automation.
This depends on the concept you are trying to express and cannot be the same in all scenarios (except for direct ones like "interface implementation").
> I'd rather not?
Well, you did ask for a concrete example and i showed you MFC apps.
> This sounds really bad to me at scale and under pressure.
Saying something is "bad" or "spaghetti" without understanding the design concepts behind the implementation is wrong. MFC is one the largest and most successful application frameworks in the industry and has proven itself in all sorts of applications at scale; studying it teaches one lots of OOD/OOP techniques (good/bad/ugly) needed in real-life industry apps.