This has its downside too though. A function designed to take an immutable class instance cannot rely on the class instance to remain unchanged, because the caller could pass it an instance of the corresponding mutable subclass! (For example, the function might use the argument as a dict key.) In some sense this inheritance pattern breaks the "Liskov substibutability" principle: if B is a base class of C, whenever a B instance is expected, a C instance may be used.
Presumably the designers of the NextStep libraries thought to themselves that they couldn't do it the other way (have NSArray subclass NSMutableArray) because NSArray couldn't provide a real implementation of a mutation method like "NSArray addObject".
If you include the immutability guarantee as well as the methods in the "contract" offered by an interface, then its clear that neither can be a Liskov-substitution-principle-preserving subtype of the other.
The E Language paid careful attention to this issue because a surprise about mutability could easily be a security hole. Their solution is quite Pythonic, inasmuch as type-checking is dynamic, structural (an object matches a type if it offers the interface regardless of whether it is explicitly declared to be a subtype), and soft (an object can implement only part of a type).
These are the three noble features of Python's type system. (I occasionally hear about efforts to cripple Python's type system in order to make it as ungainly as Java's, but fortunately they always seem to fade away...)
So in E, it's the same: if you are expecting a mutable list (a "FlexList") and you get an immutable one, you'll get an exception at run-time if you try a mutation operation like mylist.append("spam").
Like Python, E's strings do the right thing if you invoke immutable list ("ConstList") methods on them.
The syntax for constructing maps and lists and indexing them is similar to Python's. That syntax always constructs immutable structures, a mutable version of which is generated with the method "mylist.diverge()". To get an immutable version of a mutable structure, you write "mylist.snapshot()".
http://zooko.com/ ^-- newly and incompletely restored