3 ms·
The problems with subclass inheritance aren't a challenge to LSP. They're an illustration of exactly what LSP is about. In order to make it easier to follow LS
by bunderbunder 10y ago
The problems with subclass inheritance aren't a challenge to LSP. They're an illustration of exactly what LSP is about.
In order to make it easier to follow LSP, it's wise to minimize the amount of concrete implementation in your base types. The more you can minimize it, the less likely you are to encounter a situation where a base type implements behavior you don't want. That in turn reduces the spots where you might even want to violate LSP.
The logical end to this is purely abstract base classes which contain no implementation. These types are so easy to reuse that some languages have even enshrined them as their own special language construct (typically called "interfaces"), and given them special privileges that types which allow implementation don't get to enjoy, such as multiple inheritance. The reason they get these special privileges is that it's relatively easy for them to enjoy those features without violating LSP, whereas it's inherently tricky for types that include concrete implementation to do the same.
- StyloBill 10y agoI never thought about interfaces this way. Great comment.
- humanrebar 10y agoI wasn't challenging the LSP as much as saying it's practically moot, at least for me. To that end, the digression into ABCs and LSP only gives inexperienced developers a digression to explore on the way to cleaner design principles. It's also worth noting that ABCs are especially problematic when physical representation of data is concerned. Inheritance in C++ affects memory layout, for instance. And adding new serializeable members to a base class in any language is a reverse-incompatible change.
- bunderbunder 10y agoIf there's any physical representation, then it's not all the way there on the abstraction front. I meant to exclude any definition of storage format with the "that contain no implementation" qualifier, because specifying data members is necessarily specifying how you expect the storage of that information to be implemented. As a contrasting example, Java and .NET interfaces aren't allowed to contain fields, only method and property signatures. Which really means only method signatures, since Java and .NET properties are just methods + syntactic sugar. Both languages also have ABCs, but they are distinct language constructs that don't get to enjoy the same privileges as interfaces. That may mean that C++ abstract base classes don't quite hit it on the LSP front. It's also true that C++ is a language that predates LSP's formulation by over a decade, so we can't really expect it to be a language that's designed to take LSP into account, anyway. Long story short, though, just because LSP is baked into your programming language doesn't mean it's moot. It just means you're working in a language that's well-designed on that front.