Think of the method signatures of a class or interface as a contract or a promise of what it and any subclass can do.
SuperclassA
promises to do action method
for any SuperclassB
. In order for SubclassA
to be a SuperclassA
it must do action method
for all SuperclassB
. The issue is that it only does action method
for some types of SuperclassB
.
Here is the same situation with names that are easier to understand.
abstract class Pet {
// Pet methods
}
class Cat extends Pet {
// Cat methods
}
class Dog extends Pet {
// Dog methods
}
abstract class PetShop {
public abstract void groom(Pet pet);
}
The Pet shop class promises that any PetShop can groom any Pet, including dogs.
PetShop shop = new FranksPetShop();
shop.groom(new Dog());
If we define FranksPetShop like so it only defines how to groom Cat's, any other type of Pet (including dogs) is not defined.
class FranksPetShop {
@Override
public abstract void groom(Cat cat) {
// Groom that cat
}
}
To solve this FranksPetShop has to define how to groom a Pet not just a Cat.
class FranksPetShop {
@Override
public abstract void groom(Pet pet) {
// Groom that pet
}
}