3 ms·
> At the time you're writing the Vehicle class, it seems perfectly reasonable to define a setPropulsionDevice() method Are you claiming that it seems reasonabl
by zvrba 13y ago
> At the time you're writing the Vehicle class, it seems perfectly reasonable to define a setPropulsionDevice() method
Are you claiming that it seems reasonable to be able to replace a car engine with a jet engine without changing anything else? (The car's hull, construction, etc., and after all these modifications it's not the "same" car anymore.)
- jeffdavis 13y agoNo. Any example I come up with is going to sound contrived, because it is. Real examples get messy, and just add to the confusion. But real issues show up due to fundamental problems with "is-a": Even if an X value "is-a" Y value, an X variable is not a Y variable (because it can't hold all objects of type Y). So passing a mutable object reference to a function is fundamentally different than passing an immutable object -- but inheritance hierarchies treat them the same. You can get around this problem by not using inheritance hierarchies that work that way, or by always using immutable objects (value semantics). But I pretty much consider the Java/C++-style inheritance to be a mess.
- dragonwriter 13y ago> But real issues show up due to fundamental problems with "is-a": Even if an X value "is-a" Y value, an X variable is not a Y variable (because it can't hold all objects of type Y). So passing a mutable object reference to a function is fundamentally different than passing an immutable object -- but inheritance hierarchies treat them the same. That's not a problem with "is-a", its a problem with unsound use of mutation in inheritance heirarchies. A mutating method can either: 1) Anticipate that it can fail, or at least the mutation component can (however that is signaled, whether by return value or exception), on some combinations of argument values and object state, in which case it works fine as a method anywhere in an inheritance hierarchy, or 2) Be guaranteed to succeed completely with any arguments of the appropriate types, in which case its fundamentally unsound anywhere except in a final class (since declaring a mutating method is essentially logically equivalent to declaring a method with a -- potentially additional -- return value whose type is simultaneously both the the type of the class it is declared in and the type of the class it is used in.