Attention : il en faut pas confondre la surcharge et la redéfinition.
Il y a redéfinition quand une sous-classe définit une méthode qui a exactement la même signature (même nom, même liste ordonnée de types d'attributs) qu'une méthode d'une surclasse. La méthode redéfinie cahce la méthode de la surclasse.
Par exemple, public String toString() qui est définie dans Object est souvent redéfinie dans toutes les classes (toutes les classes sont sous-classes de Object).
Il y a surcharge quand une sous-classe définit une méthode qui a le même nom mais un ensemble de types d'arguments différents d'une méthode d'une surclasse.
Par exemple, soit une classe Parc générique qui définit une méthode public void ajouter(Object o) throws ObjetIncompatibleException.
Admettons qu'une sous-classe ParcDeVehicules définisse une méthode spécialisée dont la signature est "public void ajouter(Vehicule v)". Il s'agit d'une surcharge. En effet, le nom de la méthode est identique (ajouter), mais le type du premier (et seul) paramètre est différent : Vehicule au lieu de Object. Du coup, il est toujours possible que la méthode ajouter(Object o) définie dans Parc soit appelée sur un ParcDeVehicules.
Exemple :
ParcDeVehicules pv= new ParcDeVehicules() ;
Fruit f = new Citron() ;
pv.ajouter(f) ; // la méthode ajouter(Object o) définie dans Parc est appelée sur pv
Vehicule v = new Voiture() ;
pv.ajouter(v) ; // la méthode ajouter(Vehicule v) définie dans ParcDeVehicules est appelée sur pv
Object o = new Voiture() ;
pv.ajouter(o) ; // la méthode ajouter(Object o) définie dans Parc est appelée sur pv
pv.ajouter((Vehicule)o) // la méthode ajouter(Vehicule v) définie dans ParcDeVehicules est appelée sur pv
Pour s'assurer que l'on ne peut ajouter que des instances de Vehicule dans un ParcDeVehicule, il faudra cacher dans ParcDeVehicules la méthode ajouter(Object o) définie dans Parc en redéfinissant cette méthode de la sorte dans ParcDeVehicules :
public void ajouter(Object o) throws ObjectIncompatibleException {
try {
this.ajouter((Vehicule)o);
}
catch ClassCastException {
throw new ObjectIncompatibleException()
}
}
La redéfinition remplace la méthode de la surclasse.
Conséquences sur l'exemple :
ParcDeVehicules pv= new ParcDeVehicules() ;
Fruit f = new Citron() ;
pv.ajouter(f) ; // la méthode ajouter(Object o) définie dans ParcDeVehicules est appelée sur pv et le downcast impropre provoque une exception, qui est capturée pour générer l'exception ObjetIncompatibleException
Vehicule v = new Voiture() ;
pv.ajouter(v) ; // la méthode ajouter(Vehicule v) définie dans ParcDeVehicules est appelée sur pv
Object o = new Voiture() ;
pv.ajouter(o) ; // la méthode ajouter(Object o) définie dans ParcDeVehicules est appelée sur pv, Voiture étant sous-classe de Vehicule, le cast fonctionne et la méthode ajouter(Vehicule v) définie dans ParcDeVehicule est appelée
pv.ajouter((Vehicule)o) // la méthode ajouter(Vehicule v) définie dans ParcDeVehicules est appelée directement sur pv

