CSI1502 Principes fondamentaux en conception des logiciels Chapitre 7: Lhéritage
2 Objectifs du cours: Lhéritage Une autre technique OO fondamentale dénommé l`héritage, pour organiser et créer des classes et promouvoir leur réutilisation. Comprendre ce qui suit: Dériver de nouvelles classes de classes existantes Créer des hiérarchies de classe: une classe parent et de classes enfants Le modificateur d`accès protected Le Polymorphisme via l`héritage Hiérarchies héréditaires pour les interface
3 Qu`est-ce qu`est l`héritage? L`héritage permet au programmeur de dériver de nouvelles classes à partir de classe existante. La classe existante est dénommé la classe parent, ou super classe (superclass) ou classe de base (base class). La classe dérivé est dénommé classe enfant ou sous- classe (subclass) Comme le nom indique, l`enfant hérite des caractéristiques de la classe parent. C`est à dire que la classe enfant hérite: Des méthodes et données définis dans la classe parent
4 L`héritage : Idée principale Afin d`ajuster la classe dérivée un programmeur peut: Ajouter de nouvelles variables ou méthodes, ou Modifier les éléments hérités La réutilisant de logiciel est au coeur de l`héritage En utilisant des objets logiciels existants afin de créer d`autres objets logiciels, nous bénéficions de tout le travail qui à été mis dans la création, implémentation et vérification des logiciels existants.
5 Visualisation de l`héritage Les relations héritage sont souvent montrées de façon graphiques dans les diagramme de classe, avec une flèche allant vers la classe parent L`héritage crée une relation «est un(e)» (is-a), soit que l`enfant est une version plus spécifique que le parent Vehicle Car
6 Dérivation de sous classes En Java, le mot réservé extends est utilisé pour établir une relation d`héritage class Car extends Vehicle { // class contents } Voir Words.java, Book.java et Dictionary.java (pp.384++)
7 Diagramme UML montrant l`héritage Words + main (args : String[]) : void + definitionMessage( ): void Dictionary - definition: int + pageMessage( ):void # pages: int Book
8 Programme pilote: Words.java public class Words { //Instansiates a derived class public static void main (String[] args) { Dictionary webster= new Dictionary(); webster.pageMessage(); webster.definitionMessage(); } }
9 Book.java: La Classe Parent public class Words { //Instansiates a derived class public static void main (String[] args) { Dictionary webster= new Dictionary(); webster.pageMessage(); webster.definitionMessage(); } }
10 Dictionary.java: La classe enfant public class Dictionary extends Book { private int definitions = 52500; public void definitionMessage() { System.out.println("Number of definitions: " + definitions); System.out.println("Definitions per page: " + definitions/pages); } } Number of pages: 1000 Number of definitions: Definitions per page: 52
11 Modificateur d`accès: Le modificateur protected Les modificateurs d`accès déterminent quels membres de la classe sont héritable et lesquels ne le sont pas Les variables et méthodes déclarées avec un modificateur public sont héritées; ceux avec un modificateur private ne le sont pas Mais le variables public violent le principe d`encapsulation Il existe un troisième modificateur d`accès qui aide les situation d`héritage: protected
12 Le modificateur protected Le modificateur d`accès protected permet à un membre de la classe parent a être hérité par l`enfant Le modificateur protected donne une meilleure encapsulation que le modificateur public. Malgré ça, le modificateur protected n`a pas une encapsulation plus forte que le modificateur private Plus de détails sure chaque modificateur est donné dans l`appendice F.
13 Référence à un parent: La référence super Les constructeurs ne sont pas héritables, malgré leur modificateur public Et pourtant souvent nous voudrions utiliser le constructeur de la classe parent afin d`initialiser la «partie du parent» dans l`objet La référence super peut-être utilisée pour invoquer la classe parent, et souvent est utilisé pour invoquer le constructeur de celui-ci Voir l`exemple Word2, pp
14 Le programme pilote: Words2.java public class Words2 { //Instansiates a derived class public static void main (String[] args) { Dictionary2 webster= new Dictionary2(1500, 52500); webster.pageMessage(); webster.definitionMessage(); } } Number of pages: 1500 Number of definitions: Definitions per page: 35
15 La classe parent: Book2.java public class Book2 { protected int pages; public Book2(int numPages) { pages = numPages; } // print a message public void pageMessage() { System.out.println("Number of pages: " + pages); } }
16 La classe enfant: Dictionary2.java public class Dictionary2 extends Book2 { private int definitions; public Dictionary2(int numPages, int numDefinitions) { super(numPages); definitions = numDefinitions; } public void definitionMessage() { System.out.println("Number of definitions: " + definitions); System.out.println("Definitions per page: + definitions/pages); }
17 Plus au sujet de la référence super Un constructeur d`une classe enfant et responsable d`appeler le constructeur du parent La première ligne du constructeur doit utiliser la référence super afin d`appeler le constructeur du parent La référence super peut aussi être utilisé afin d`accéder à d`autres variables et méthodes définies dans la classe parent
18 L`héritage simple vs. l`héritage multiple Java ne supporte que l`héritage simple, soit qu`une classe dérivé ne peut n`avoir qu`un seul parent! Certains autre langages supportent l`héritage multiple, ce qui permet à certaines classes d`être dérivées de plusieurs classe bénéficiant de toutes les variables et méthodes de ses parent Ceci implique que les collisions, tel que d`avoir deux variables du même nom doivent alors être résolues Dans la plus part des cas, l`utilisation d`interface nous donne les avantages de l`héritage multiple sans la complexité
19 L`outrepassement de méthodes Une classe enfant peut outrepasser la définition d`une méthode hérité en faveur de sa propre méthode C`est à dire, que un enfant peut redéfinir une méthode héritée de son parent La nouvelle méthode doit avoir la même signature que la méthode du parent, mais peut avoir un fonctionnalité différente. Le type de l`objet en train d`exécuter détermine quel version de la méthode qui doit être invoquée
20 L`outrepassement de méthodes : Messages.java (p.392) public class Messages { public static void main (String[] args) { Thought parked = new Thought(); Advice dates = new Advice(); parked.message(); dates.message(); } } I feel fine Warning: Time is shrinking
21 Thought.java public class Thought { public void message() { System.out.println("I feel fine"); System.out.println(); } }
22 Advice.java public class Advice { public void message() { System.out.println("Warning: Time is shrinking"); System.out.println(); } } public class Advice extends Thought { public void message() { System.out.println("Warning: Time is shrinking"); System.out.println(); super.message(); }}
23 L`outrepassement de méthodes et de variables Notez que la méthode parent peut être invoqué spécifiquement en utilisant la référence super Si une méthode est déclaré avec le modificateur final, on ne peut l`outrepasser Le concept d`outrepassement peut aussi être appliqué au variables (dénommé shadowing variables en anglais). Mais ceci, de règle générale, est non recommandé
24 La surcharge de méthodes vs. l`outrepassement de méthodes La surcharge de méthodes concerne plusieurs méthodes dans une même classe ayant le même nom mais pas la même signature. L`outrepassement de méthodes concerne deux méthodes l`une dans une classe parent l`autre dans la classe enfant ayant le même nom et la même signature. La surcharge de méthodes vous permet de définir des opérations similaires de façon différentes pour différentiels type de données L`outrepassement de méthodes vous permet de définir une opération similaire de façon différente pour des objets différents.
25 Hiérarchies de classe Une classe enfant d`un parent peut-être le parent d`une autre classe enfant, créant ainsi une Hiérarchies de classe Business RetailBusinessServiceBusiness KMartMacysKinkos
26 Hiérarchies de classe: Quelques définitions Deux enfants du même parents sont dénommé «siblings» Un bon concept est de mettre les aspects commun aussi haut que raisonnable dans une hiérarchie Un membre héritable se fait passer dans tous les enfants Le mécanisme d`héritage est transitif C`est à dire que une classe enfant hérite de tous ces ancêtres Il n`existe pas «La» hiérarchie de classe qui est appropriée dans toutes les situations Les hiérarchies de classes doivent souvent être modifiées et améliorées afin de rester utile
27 La classe Object : Incluse dans java.lang Toutes les classes sont dérivées de la classe Object La classe Object est l`ultime parent de toute les hiérarchies de classe La classe Object contient quelques méthodes utiles qui sont hérité par toutes les classes Par exemple, la méthode toString est définie dans la classe Object C`est pourquoi la méthode println peut appeler toString pour tous les objets qui lui est passé – tous les objets sont garantis d`avoir une méthode toString par l`héritage
28 Classes Abstraites Une classe abstraite est une classe qui représente un concept générique dans une hiérarchie Une classe abstraite ne peut-être utilisé Nous utilisons le modificateur abstract sur la l`entête de la classe pour déclarer une classe abstraite abstract public class vehicle
29 Que sont les Classes Abstraites? Une classe abstraite contient souvent des méthodes sans définitions (comme les interfaces), mais ce n`est pas obligatoire Contrairement à une interface, le modificateur abstract peut-être appliqué à chaque méthode abstraite Une classe abstraite contient typiquement des méthodes non abstraites avec des méthodes fonctionnelles, faisant la différence entre les classes abstraites et les interfaces Une classe déclaré abstraite ne doit pas nécessairement contenir des méthodes abstraites.
30 Que sont les Classes Abstraites? L`enfant d`une classe abstraite doit outrepasser les méthodes abstraites du parent, sinon l`enfant va aussi devenir avstrait Une méthode abstraite ne peut être définie comme final (car la méthode doit être outrepassée) static (car la méthode n`est pas définie) L`utilisation d`une classe abstraite est une décision de concept; cela permet de créer des éléments communs dans une classe trop générale pour être utile. Par exemple Vehicle, FuelConsumption Employee, BenefitsCalculation
31 Utilisation indirecte de membres d`une classe: Références et héritage Un objet référé peut faire référence à un objet de sa classe, ou à un objet de n`importe quel autre classe relié par héritage Par exemple, si la classe Holiday est utilisé pour dériver un enfant dénommé Christmas, alors une référence Holiday peut-être utilisé pour pointer sur un objet Christmas Holiday Christmas Holiday day; day = new Christmas();
32 Références et héritage : Ouverture vs fermeture Conversion d`ouverture («Widening conversion»): Assigner un objet prédécesseur à une référence d`ancêtre Fait par une simple assignation Conversion de fermeture («Narrowing conversion»): Assigner un objet d`ancêtre prédécesseur à une référence de prédécesseur Fait par un conversion («cast»)
33 Utilisation indirecte de membres non hérités Un membre hérité peut être référencé directement par nom dans la classe enfant, tout comme si il y fût déclaré Mais, même si une méthode ou variable n`est pas hérité par l`enfant, on peut encore y accéder au travers des méthodes du parent Voir FoodAnalysis.java (page 403) FoodAnalysis.java Voir FoodItem.java (page 404) FoodItem.java Voir Pizza.java (page 405) Pizza.java
34 FoodAnalysis.java public class FoodAnalysis { public static void main (String[] args) { Pizza special = new Pizza(275); System.out.println("Calories per serving: " + special.caloriesPerServing()); } } Calories per serving: 309
35 FoodItem.java public class FoodItem { final private int CAL_PER_GRAM = 9; private int fatGrams; protected int servings; public FoodItem(int numFatGrams, int numServings) { fatGrams = numFatGrams; servings = numServings; } private int calories() { return fatGrams*CAL_PER_GRAM; } public int caloriesPerServing() { return (calories()/servings); } }
36 Pizza.java public class Pizza extends FoodItem { public Pizza(int fatGrams) { super(fatGrams, 8); } }
37 Polymorphisme: Avoir plusieurs formes Une référence peut être polymorphique, ce qui peut être défini comme «avoir plusieurs formes» Une variable référencé polymorphique peut référer à différent types d`objets durant l`exécution Les références polymorphiques sont résolues durant l`exécution; ceci est dénommé «dynamic binding» L`utilisation prudente de références polymorphiques permet de construire des logiciels élégant et robustes. Mammal pet; Horse myhorse = new Horse(); // Horse derived from Mammal // Horse is-a Mammal pet = myhorse;
38 Polymorphisme via héritage Supposons que la classe Holiday à une méthode dénommé celebrate, et que la classe Christmas l`outrepasse Considérons maintenant l`invocation suivante: day.celebrate(); Si day référe à un objet Holiday, il invoce la version celebrate de Holiday ; de même pour l`objet Christmas
39 Polymorphisme via héritage Considérons la hiérarchie de classe suivante: StaffMember VolunteerEmployee ExecutiveHourly Considérons maintenant la tâche de payer tous les employés
40 Firm.java public class Firm { public static void main (String[] args) { Staff personnel = new Staff(); personnel.payday(); } } Name: Sam Phone: Paid: Name: Joe Phone: Paid: Name: Sue Phone: Thanks! Name: Ann Phone:
41 Staff.java public class Staff { private StaffMember[] staffList; public Staff() { staffList = new StaffMember[4]; staffList[0] = new Executive("Sam", " ", ); staffList[1] = new Employee("Joe", " ", ); staffList[2] = new Volunteer("Sue", " "); staffList[3] = new Volunteer("Ann", " "); } Continued…
42 Staff.java (cont.) … public void payday() { double amount; for (int count = 0; count < staffList.length; count++) { System.out.println(staffList[count]); amount = staffList[count].pay(); if (amount == 0) System.out.println("Thanks!"); else System.out.println("Paid: " + amount); } } }
43 StaffMember.java abstract public class StaffMember { protected String name; protected String phone; public StaffMember(String eName, String ePhone) { name = eName; phone = ePhone; } public String toString() { String result = "Name: " + name + "\n"; result += "Phone: " + phone; return result; } public abstract double pay(); }
44 Volunteer.java public class Volunteer extends StaffMember { public Volunteer (String eName, String ePhone) { super(eName, ePhone); } public double pay() { return 0.0; } }
45 Employee.java public class Employee extends StaffMember { protected double payRate; public Employee(String eName, String ePhone, double rate) { super(eName, ePhone); payRate = rate; } public double pay() { return payRate; } public String toString() { String result = super.toString(); return result; } }
46 Executive.java public class Executive extends Employee { private double bonus; public Executive(String eName, String ePhone, double rate) { super(eName, ePhone, rate); bonus = 1000; } public double pay() { double payment = super.pay() + bonus; return payment; } }
47 Hiérarchies d`interface L`héritage peut-être appliqué aux interfaces aussi bien qu`aux classes Une interface peut-être dérivé d`une autre interface L`interface enfant hérite toutes les méthodes abstraites du parent Une classe implémentant l`interface enfant doit définir toutes les méthodes de l`interface du parent ainsi que ceux de l`enfants Tous les membres d`une interface sont public Notez que les hiérarchies de classes et hiérarchies d`interface sont distinctes
48 Polymorphisme via Interfaces Un nom d`interface peut-être utilisé pour déclarer une variable d`objet référence Les interfaces permettent des références polymorphiques dans lesquelles la méthode qui se fait invoquer est determiné par l`objet référencé
49 Speakers, Philosophers and Dogs public interface Speaker { public void speak(); public void announce (String str); } Assumons les classes Philosopher et Dog sont implementé en utilisant l`interface Speaker: Speaker guest; guest = new Philosopher(); guest.speak(); speak method dans la classe Philosopher guest = new Dog(); guest.speak; speak method dans la classe Dog
50 Héritage et GUIs: Plus à ce sujet dans le Chapitre 9 Un applet est un excellent exemple d`héritage Rappelons nous que lors de la définition d`un applet, on étend la classe Applet ou la classe JApplet Les classes Applet et JApplet s`occupent de tous les détails pour la création et l`exécution d`un applet, incluant les interactions avec le fureteur Quand nous définissons certaines méthodes, tel que paint d`un applet, en effet nous outrepassons la méthode définie dans la classe Component, qui est ultimement hérité dans les Applet ou JApplet
51 Sommaire: Chapitre 7 Comprendre ce qui suit: Dériver de nouvelles classes de classes existantes Créer des hiérarchies de classe: une classe parent et de classes enfants Le modificateur d`accès protected Le Polymorphisme via l`héritage Hiérarchies héréditaires pour les interface