Introduction la programmation objet avec Java Cours 5
Introduction à la programmation objet avec Java Cours 5 : héritage (1ère partie) 1. Un exemple d'héritage 2. Héritage 3. Créer et initialiser une instance d'une classe étendue 4. Invoquer des méthodes d'une classe étendue 5. Accès protégé (protected) B. Lemaire
1. Un exemple d'héritage 2
Exemple de code redondant (répété) public class Animal { private float poids ; public class Mammifere { private float poids ; private int nb. Mamelles ; public Animal(float p) { this. poids = p ; } public Mamifere(float p, int m) { this. poids = y ; public float get. Poids( ) { return this. poids ; } } this. nb. Mamelles = m ; public int get. Nb. Mamelles( ) { return this. nb. Mamelles ; } public void affiche( ) { System. out. println (this. poids) ; } } // fin classe Animal public void affiche() { System. out. println (this. poids) ; System. out. println (this. mamelles) ; } } // fin classe Mammifere 3
Exemple de code non redondant grâce à l'héritage La classe Mammifere est une extension de la classe Animal, public class Animal { private float poids ; public class Mammifere extends Animal { private int nb. Mamelles ; public Animal(float p) { this. poids = y ; } public Mammifere(float p, int m) { super(p) ; this. nb. Mamelles = m ; } public float get. Poids( ) { return this. poids ; } public int get. Nb. Mamelles( ) { return this. nb. Mamelles ; } public void affiche( ) { System. out. println (this. poids) ; } }// fin classe Animal public void affiche( ) { super. affiche( ) ; } System. out. println (this. mamelles) ; } // fin classe Mammifere 4
Un classe étendue contient une partie implicite héritée et une partie explicite public class Mammifere extends Animal { private int nb. Mamelles ; private float poids ; public Mamifere(float p, int m) { super(p) ; this. nb. Mamelles = m ; } public Animal(float p) { this. poids = y ; } public int get. Nb. Mamelles( ) { return this. nb. Mamelles ; } public float get. Poids( ) { return this. poids ; } public void affiche( ) { super. affiche( ) ; public void affiche( ) { System. out. println (this. poids) ; } } System. out. println (this. mamelles) ; partie explicite spécifique à Mammifere partie implicite héritée de Animal (n'apparaît pas dans Mammifere) } // fin classe Mammifere 5
2. Héritage 6
Caractéristiques de l'héritage L'héritage permet de définir une nouvelle classe à partir d'une classe existante en ne spécifiant que ce qu'elle ajoute (on ne peut rien retirer) Animal - float poids + Animal(float p) (partie héritée implicite) + float get. Poids( ) + String to. String( ) Mammifere public class Mammifere extends Animal { - int nb. Mamelles + Mamifere(float p, int m) (partie spécifique explicite) + float get. Nb. Mamelles( ) + String to. String( ) (notation UML) } 7
Vocabulaire On dit de façon équivalente que : Animal • la classe Mammifere hérite de la classe Animal • la classe Mammifere étend la classe Animal Mammifere • la classe Mammifere est une classe fille de la classe Animal • la classe Animal est la classe mère de la classe Mammifere • la classe Mammifere est une sous classe (ou classe dérivée) de la classe Animal • la classe Animal est la sur-classe de la classe Mammifere • la classe Mamifere est plus spécifique la classe Animale • la classe Animal est plus générale que la classe Mammifere 8
Règles d'héritage en java Animal Plusieurs classes peuvent hériter d'une même classe Mammifere Animal. Marin mais Mammifere. Marin une même classe ne peut hériter de plusieurs classes en Java (pas d'héritage multiple) 9
Intérêts de l'héritage Réutilisation et factorisation Animal Mammifere Souris Elephant 1 – Réutilisation : concevoir de nouvelles classes à partir de classes déjà correctement définies gain important de temps de développement + minimisation des risques d'erreurs 2 - Factorisation : mise en commun des variables et méthodes gain de place 10
Classe non extensible Une classe précédée du mot-clé final ne peut être étendue extends Object est implicite public final class Point. Plan {. . . Object } // fin classe Point. Plan public class Point. Colore extends Point. Plan { private int couleur ; . . . } // fin classe Souris rejet du compilateur : Point. Plan est une classe finale 11
3. Créer et initialiser une instance d'une classe étendue 12
Instance d'une classe étendue Une instance d'une classe étendue contient : les variables d'instance héritées + les variables d'instance spécifiques public class Animal { public class Mammifere extends Animal { private int nb. Mamelles ; private float poids ; … … } // fin classe Mammifere } // fin classe Animal { } : Mammifere - poids 30 f - nb. Mamelles 6 Mammifere m 1 = new Mammifere(30 f , 6) ; Mammifere m 2 = new Mammifere(50 f , 4) ; : Mammifere - poids 50 f - nb. Mamelles 4 13
Les variables d'instances héritées sont initialisées par un constructeur de la classe mère public class Mammifere extends Animal { private int nb. Mamelles ; public Mammifere(float p, int m) { super(p) ; this. nb. Mamelles = m ; } public class Test. Mammifere { public static void main(String[ ] args) { Mammifere m = new Mammifere(30 f, 6) ; } // fin main } // fin classe . . . super(p) Animal(p) : appelle du constructeur de la classe mère : obligatoirement en 1ère instruction du constructeur ! En cas d'omission il y a un appel implicite super( ) (provoque une erreur de compilation si la classe mère n'a pas de constructeur vide) } // fin classe Mammifere : Mammifere - poids 30 f - nb. Mamelles 6 14
Le constructeur de la classe mère invoqué est choisi en fonction de sa signature public class Mammifere extends Animal { private int nb. Mamelles ; public class Animal { private float poids ; public Animal(float p) { this. poids = y ; } public Mamifere(float p, int m) { } public Animal ( ) { this. poids = 50 f ; } super(p) ; this. nb. Mamelles = m ; public Mamifere(int m) { } // fin classe Animal super( ) ; this. nb. Mamelles = m ; } } // fin classe Mammifere : Mammifere - poids 30 f - nb. Mamelles 6 : Mammifere - poids 50 f - nb. Mamelles 4 { Mammifere m 1 = new Mammifere(30 f, 6) ; } Mammifere m 2 = new Mammifere(4) ; 15
4. Invoquer des méthodes d'une classe étendue 16
Invoquer une méthode spécifique (Une méthode spécifique n'existe pas dans la classe mère) public class Mammifere extends Animal { private int nb. Mamelles ; public Mamifere(float p, int m) { } public class Test. Mammifere { public static void main(String[] args) { Mammifere m 1 = new Mammifere(30 f, 6) ; int n = m 1. get. Nb. Mamelles( ) ; super(p) ; this. nb. Mamelles = m ; } } // fin classe Test. Mammifere public int get. Nb. Mamelles( ) { return this. nb. Mamelles ; } : Mammifere } // fin classe Mammifere - poids 30 f - nb. Mamelles 6 17
Invoquer une méthode héritée public class Animal { private float poids ; . . . public float get. Poids( ) { return this. poids ; } } // fin classe Animal public class Mammifere extends Animal { private int nb. Mamelles ; public class Test. Mammifere { public static void main(String[] args) { Mammifere m 1 = new Mammifere(30 f, 6) ; int p = m 1. get. Poids( ) ; } } // fin classe Test. Mammifere public Mamifere(float p, int m) { } méthode héritée de Animal super(p) ; this. nb. Mamelles = m ; } // fin classe Mammifere : Mammifere - poids 30 f - nb. Mamelles 6 18
Redéfinir une méthode héritée Écrire une méthode spécifique de même signature qu'une méthode héritée public class Animal public class Mammifere extends Animal { { public void qui. Suis. Je( ) { System. out. println("je suis un animal") ; } … } // fin classe Animal … public void qui. Suis. Je( ) { System. out. println ("je suis un mammifère") ; } } // fin classe Mammifere La classe Mammifere possède 2 méthodes qui. Suis. Je( ) de même signature : on dit que qui. Suis. Je( ) a été redéfinie Redéfinir surcharger (surcharger = écrire une méthode de même nom mais de signature différente) 19
Etendre une classe pour redéfinir des méthodes Il n'y a aucune obligation à ajouter de nouvelles variables et/ou méthodes dans une classe étendue (on pourrait même ne rien changer) On étend parfois une classe pour simplement redéfinir certaines de ses méthodes (et ainsi changer le comportement de ces méthodes dans la classe étendue) ex) Pour créer une classe Triangle étendant la classe Polygone il est juste nécessaire de redéfinir la méthode init( ) (pour assurer qu'exactement 3 sommets seront créés et initialisés). On peut aussi ajouter une spécifique méthode surface( ) retournant la surface d'une triangle 20
Invoquer une méthode redéfinie C'est toujours la méthode spécifique (appartenant à la classe fille) qui est invoquée public class Animal { public void qui. Suis. Je( ) { System. out. println("Je suis un animal") ; } } // fin classe Animal public class Mammifere extends Animal { … public void qui. Suis. Je( ) public class Test. Mammifere { public static void main(String[] args) { Mammifere m 1 = new Mammifere(30 f, 6) ; m 1. qui. Suis. Je( ) ; } } // fin classe Test. Mammifere { System. out. println ("Je suis un mammifère") ; } } // fin classe Mammifere c'est la méthode qui. Suis. Je( ) de la classe Mammifere qui est invoquée. Elle est plus spécifique celle de Animal. Affichage : "je suis un mammifère" La méthode héritée qui. Suis. Je( ) est masquée par sa redéfinition 21
Invoquer une méthode masquée public class Animal { Utiliser le mot clé super public String to. String( ) { return ("poids = " + this. poids) ; } } // fin classe Animal public class Mammifere extends Animal { … public String to. String( ) { } return (super. to. String( ) + ", nb mamelles = " + + this. nb. Mammelles) ; public class Test. Mammifere { public static void main(String[] args) { Mammifere m 1 = new Mammifere(30 f, 6) ; } appelle la méthode to. String( ) héritée de la classe mère (Animal). System. out. println(m 1) ; } // fin classe Test. Mammifere Affichage : "poids = 30, nb mamelles = 6" } // fin classe Mammifere 22
super est une référence Une instance référencée par super est considérée comme étant une instance la classe mère public class Mammifere extends Animal { … public String to. String( ) { } public class Test. Mammifere { public static void main(String[] args) { return (super. to. String( ) + ", nb mamelles = " + + this. nb. Mammelles) ; … Mammifere m 1 = new Mammifere(30 f, 6) ; System. out. println(m 1) ; } } // fin classe Test. Mammifere l'instance référencée par super est considérée comme une instance d'Animal et non de Mammifere aussi c'est la méthode to. String( ) héritée d'Animal qui est invoquée } // fin classe Mammifere : Mammifere - poids 30 f - nb. Mamelles 6 23
5. Accès protégé (protected) 24
Les variables privées héritées sont inaccessibles dans la classe fille public class Animal { private float poids ; … } // fin classe Animal public class Mammifere extends Animal { private int nb. Mamelles ; public void affiche () { System. out. println (this. poids + " this. nb. Mamelles) ; } rejet du compilateur : poids est une variable privée (private) … } // fin classe Mammifere 25
protected : un accès intermédiaire entre private et public Tout membre (variable ou méthode) d'une classe ayant l'accès protected est considéré : - publique (public) : 1) depuis les classes filles 2) depuis toute classe située dans le même paquetage - privé (private) dans tous les autres cas public class Animal { protected float poids ; // fin classe Animal } public class Mammifere extends Animal { private int nb. Mamelles ; public void affiche () { System. out. println (this. poids + " this. nb. Mamelles) ; } ok } // fin classe Mammifere 26
L'accès protégé rend l'encapsulation perméable Pour une classe fille ou une classe du même paquetage un membre protected membre public class Animal { public class Mammifere extends Animal { private int nb. Mamelles ; protected float poids ; public void modifie () { this. poids = - 15 ; } // fin classe Animal } on peut modifier la variable d'instance héritée poids dans la sous-classe } // fin classe Mammifere Il vaut mieux utiliser l'accès private et donner un accès au moyen de méthodes d'accès public ou protected 27
- Slides: 27