if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e. an object of type T may be substituted with any object of a subtype S) without altering any of the desirable properties of the program
- Method parameter types are contravariant, i.e. if you override a method, the overriding method in the subtype must accept parameters of the same types or more general types as the overridden method.
- Method return types are covariant, i.e. the overriding method in a subtype must return the same type or a more specific type as the overridden method.
- Methods in subtypes must not raise any new exceptions that are not only raised by the overridden method in the supertype, except for exceptions whose types are themselves subtypes of the exceptions raised by the overridden method.
- Preconditions cannot be strengthened in a subtype, i.e. if you replace an object with a subtype, you cannot impose additional restrictions on the caller, since the