I think you've got the right idea, but you've overgeneralized the critique of subclassing by suggesting that it is contradictory.
Here's where you're 100% correct: a subclass should not change the specified behavior of its superclass. To do so would be a violation of the contract established by its superclass's API.
This does not, however, apply to all use of subclassing. Rather, a superclass's API can be specified in such a way that subclasses may change behavior without breaking the contract. Dog and Animal fit this mold -- the Animal API may specify that Speak() will "cause the animal to speak", intentionally leaving this behavior up to subclassers. This is core to how subtyping-based polymorphism works -- the superclass underconstrains its API in order to allow subclasses to later tighten those constraints while still providing valid implementations of the superclass's contract.
Good API design requires that interface behaviors are properly constrained. Overconstrain them, and you box yourself (and consumers of the API) out of useful abstractions. Underconstrain them and it becomes impossible to work with the APIs because consumers of the API can't count on subclasses to have the proper behavior.
It's very, very easy to accidentally underconstrain an API, as you aptly pointed out. UIView does this with its subviews array. By exposing this mutable list, it broadcasts to its consumers a huge set of APIs that make promises they can't keep. If more thought had been put into how UIViews should be subclassed, they might have further constrained it so that (for example) a UIView is responsible for maintaining and keeping internally consistent its set of subviews. This is a promise that subclasses can keep (probably by not publicly exposing subviews at all, since making it public is likely to, again, result in underconstrained APIs and more API promises it can't keep), and assumptions that are useful for consumers of the API (e.g. "I don't have to worry about managing subviews that aren't explicitly called out in the contract" or "a layout container can't accidentally mess up its contents' subviews").
FWIW, XAML's UI framework does draw these types of distinctions, making _most_ of its subtyping sane (take a look at UIElement, FrameworkElement, Control, ContentControl, and Panel). Every now and then you can find examples where the abstractions are leaky due to under/overconstraining the APIs (e.g. the subtle differences between UserControl and ContentControl... UserControl looks like you could use it instead of ContentControl in most cases because the Content property is publicly settable and probably shouldn't be -- an API decision that every UserControl subclass has to live with and usually chooses to ignore).
Anyway, my point is this: subclassing is _not_, at its core, contradictory. But API designers _must_ design classes to be subclassed. In order to properly answer the "is X a Y?" question, subclassers must also be able to assert that X's implementation meets all of the constraints of Y's API.
Here's where you're 100% correct: a subclass should not change the specified behavior of its superclass. To do so would be a violation of the contract established by its superclass's API.
This does not, however, apply to all use of subclassing. Rather, a superclass's API can be specified in such a way that subclasses may change behavior without breaking the contract. Dog and Animal fit this mold -- the Animal API may specify that Speak() will "cause the animal to speak", intentionally leaving this behavior up to subclassers. This is core to how subtyping-based polymorphism works -- the superclass underconstrains its API in order to allow subclasses to later tighten those constraints while still providing valid implementations of the superclass's contract.
Good API design requires that interface behaviors are properly constrained. Overconstrain them, and you box yourself (and consumers of the API) out of useful abstractions. Underconstrain them and it becomes impossible to work with the APIs because consumers of the API can't count on subclasses to have the proper behavior.
It's very, very easy to accidentally underconstrain an API, as you aptly pointed out. UIView does this with its subviews array. By exposing this mutable list, it broadcasts to its consumers a huge set of APIs that make promises they can't keep. If more thought had been put into how UIViews should be subclassed, they might have further constrained it so that (for example) a UIView is responsible for maintaining and keeping internally consistent its set of subviews. This is a promise that subclasses can keep (probably by not publicly exposing subviews at all, since making it public is likely to, again, result in underconstrained APIs and more API promises it can't keep), and assumptions that are useful for consumers of the API (e.g. "I don't have to worry about managing subviews that aren't explicitly called out in the contract" or "a layout container can't accidentally mess up its contents' subviews").
FWIW, XAML's UI framework does draw these types of distinctions, making _most_ of its subtyping sane (take a look at UIElement, FrameworkElement, Control, ContentControl, and Panel). Every now and then you can find examples where the abstractions are leaky due to under/overconstraining the APIs (e.g. the subtle differences between UserControl and ContentControl... UserControl looks like you could use it instead of ContentControl in most cases because the Content property is publicly settable and probably shouldn't be -- an API decision that every UserControl subclass has to live with and usually chooses to ignore).
Anyway, my point is this: subclassing is _not_, at its core, contradictory. But API designers _must_ design classes to be subclassed. In order to properly answer the "is X a Y?" question, subclassers must also be able to assert that X's implementation meets all of the constraints of Y's API.