first down-cast this argument (throwing an error if it is not of the expected type): class RationalNumber implements Comparable { int numerator; int denominator; // ... public int compareTo(Object other) { RationalNumber otherNum = (RationalNumber)other; return Integer.compare(numerator * otherNum.denominator, otherNum.numerator * denominator); } } In a language with covariant parameters, the argument to could be directly given the desired type , hiding the typecast. (Of course, this would still give a runtime error if was then called on e.g. a .) Avoiding the need for covariant parameter types Other language features can provide the apparent benefits of covariant parameters while preserving Liskov substitutability. In a language with generics (a.k.a. parametric polymorphism) and bounded quantification, the previous examples can be written in a type-safe way. Instead of defining , we define a parameterized class . (One drawback of this is that the implementer of the base class needs to foresee which types will need to be specialized in the subclasses.) class Shelter<T extends Animal> { T getAnimalForAdoption() { // ... } void putAnimal(T animal) { // ... } } class CatShelter extends Shelter<Cat> { Cat getAnimalForAdoption() { // ... } void putAnimal(Cat animal) { // ... } } Similarly, in recent versions of Java the interface has been parameterized, which allows the downcast to be omitted in a type-safe way: class RationalNumber implements Comparable<RationalNumber> { int numerator; int denominator; // ... public int compareTo(RationalNumber otherNum) { return Integer.compare(numerator * otherNum.denominator, otherNum.numerator * denominator); } } Another language feature that can help is multiple dispatch. One reason that binary methods are awkward to write is that in a call like , selecting the correct implementation of really depends on the runtime type of both and , but in a conventional OO language only the runtime type of is taken into account. In a language with Common Lisp Object System (CLOS)-style multiple dispatch, the comparison method could be written as a generic function where both arguments are used for method selection. Giuseppe Castagna observed that in a typed language with multiple dispatch, a generic function can have some parameters which control dispatch and some "left-over" parameters which do not. Because the method selection rule chooses the most specific applicable method, if a method overrides another method, then the overriding method will have more specific types for the controlling parameters. On the other hand, to ensure type safety the language still must require the