• Aucun résultat trouvé

Applications Objet : L’héritage Une définition de l'héritage [Bertrand Meyer] :

N/A
N/A
Protected

Academic year: 2022

Partager "Applications Objet : L’héritage Une définition de l'héritage [Bertrand Meyer] :"

Copied!
9
0
0

Texte intégral

(1)

Applications Objet : L’héritage

Une définition de l'héritage [Bertrand Meyer] : L'héritage est un mécanisme permettant de définir une classe par rapport à d'autres en ajoutant toutes leurs caractéristiques aux siennes.

Rappel sur la notion d’héritage :

Exemple : Zoo : on gère des mammifères et Oiseaux

Propriétés : nbVertebres, poids, dureeVieMoyenne, nomEspèce, vitesse de battement d’aile, vitesse de vol, temps maximum de vol, durée de gestation, teneur calorifique du lait

Dessiner un diagramme de classes.

Dessiner un diagramme de classes pour gérer des véhicules, à traction humaine, à moteur, des motos , des voitures , des vélos.

Dessiner un diagramme de classes puis écrire les classes en java pour gérer des produits, des produits frais et la crèmerie (Crèmerie étant une sorte de produit frais).

Java et l'héritage Java et l'héritage Java et l'héritage Java et l'héritage Soit la classe suivante:

class Produit{

private String libelle;

private int prix;

private int qteStock;

public Produit(String lbl ,int px ,int qt) { libelle = lbl;

prix = px;

qteStock = qt;

}

public int valeurStock() {

return qteStock * prix;

}

public String toString(){

return (libelle +"\t"+prix+"\t"+qteStock);

} }

Une classe AppProduit permet d'instancier des objets:

public class AppProduit{

public static void main(String arg[]){

Produit p = new Produit("poire",12,100);

System.out.println(p.toString());

} }

(2)

Si nous modélisons des produits frais qui ont une durée de validité, nous obtenons:

La classe ProduitFrais spécialise la classe Produit

En Java nous utilisons le mot réservé extends pour traduire cette relation:

class ProduitFrais extends Produit{

... private int dureeValidite;

}

Constructeur de classe dérivée.

Avant d'utiliser cette classe il nous faut régler le problème du constructeur, en effet lorsque nous écrirons:

ProduitFrais pf = new ProduitFrais ; quel constructeur sera appelé?

Un constructeur spécifique doit être écrit:

public ProduitFrais(String lbl,int px,int qt, int d){

super(lbl,px,qt);

dureeValidite = d;

}

Notez ainsi que le constructeur de ProduitFrais appelle le constructeur de Produit, grâce à l'instruction super et initialise son champ propre.

L'appel à super doit être la première instruction du constructeur de la classe dérivée.

La classe ProduitFrais est opérationnelle.

public class AppProduit{

public static void main(String arg[]){

ProduitFrais pf = new ProduitFrais("poire",12,100,10);

System.out.println(pf.toString());

} }

Le résultat obtenu n'est pas encore satisfaisant car la méthode toString est la méthode d'un Produit et pas d'un ProduitFrais,

(3)

Aussi il nous faut surcharger la méthode toString():

public String toString(){

String ch = super.toString();

return ch+"\t" +this.dureeValidite);

}

Ceci est une application du polymorphisme: si une méthode est appelée, c'est la méthode de la classe qui est utilisée, sinon c'est la méthode de sa classe parente.

Dérivations successives.

Nous pouvons rajouter une classe Cremerie, en tant que produit frais spécialisé:

En Java, la classe Cremerie va hériter de ProduitFrais:

public class Cremerie extends ProduitFrais {

private float qteMatiereGrasse;

public Cremerie(String lbl,int px,int qt, int d, float qtegras) {

super(lbl, px, qt, d);

qteMatiereGrasse = qtegras;

}

public void affiche() {

super.affiche();

System.out.println("\t"+qteMatiereGrasse);

} }

Si nous voulons clore toute spécialisation future, on utilise le mot réservé final:

public final class Cremerie extends ProduitFrais

(4)

Accessibilité des membres dans les classes dérivées.

Le mécanisme d'héritage ne rompt pas le principe d'encapsulation. Il est interdit à toute classe dérivée d'accéder aux données privées de sa super-classe. Ainsi une classe dérivée est soumise aux mêmes règles qu'une classe quelconque.

Il peut être utile parfois de donner aux classes dérivées l'accès à des données d'une super-classe, ceci est possible grâce au modificateur protected ( protégé).

Si l'on déclare:

class ProduitFrais extends Produit{

protected int dureeValidite;

}

alors la classe dérivée Cremerie a accès à la donnée dureeValidite, et ce droit est transmis aux classes dérivées de Cremerie; par contre la donnée dureeValidite reste privé pour la super-classe Produit.

Remarque: une méthode peut aussi être déclarée protected.

Ne tomber pas dans la facilité apparente de déclarer tous les attributs protégés, cela entraîne des conséquences incontrôlables: dérivation pour contourner l'encapsulation.

(5)

Exemples d’héritage

Exercice : Ville et capitale public class Ville {

private String nom;

private int population;

public Ville(String nom, int population) { this.nom = nom;

this.population = population;

}

public class Capitale extends Ville { private String pays;

public Capitale(String nom, int population , String pays) { super(nom, population);

this.pays=pays;

}

public class UtiliseVille {

public static void main(String[] args) { Ville v1 = new Ville("Rampillon" , 53);

Capitale c1 = new Capitale("Paris", 2000000 , "France");

Exercice : Boisson et boisson alcoolisée public class Boisson {

private String nom;

private double prix;

public Boisson(String nom) { this.nom = nom;

}

public String getNom() { return nom;

}

public double getPrix() { return prix;

}

public void setPrix(double prix) { this.prix = prix;

} }

--- public class BoissonAlcoolisee extends Boisson {

private int degreAlcool;

public BoissonAlcoolisee(String nom, double prix, int degreAlcool) { super(nom);

super.setPrix(prix);

this.degreAlcool = degreAlcool;

}

public int getDegreAlcool() { return degreAlcool;

} }

--- public class Boissons {

public static void main(String[] args) {

Boisson jus = new Boisson("Jus d orange");

jus.setPrix(2);

BoissonAlcoolisee porto = new BoissonAlcoolisee("Porto",6.5, 18);

} }

(6)

Classes et méthodes abstraites

Classe abstraite.

Voici un diagramme de classes dans lequel les produits se déclinent en deux versions, des produits frais et des produits d'épicerie.

La classe Produit est un peu particulière, car aucun Produit ne sera instancié, en effet ce seront soit des produits d'épicerie, soit des produits frais; on dit que la classe « Produit » est abstraite.

Les façons de représenter une classe abstraite sur un diagramme UML sont : - l’utilisation du style "italique" qui indique une classe abstraite.

- Mettre le mot ‘Abstraite’ ou ‘Abstract’ devant le nom de la classe - Indiquer en commentaire que cette classe est abstraite

En Java on écrira:

public abstract class Produit{

private String libelle;

private int prix;

private int qteStock;

public Produit(String lbl,int px,int qt){

libelle = lbl;

prix = px;

qteStock = qt;

}

public int valeurStock(){

return qteStock * prix;

} }

class Epicerie extends Produit{

private int poids;

public Epicerie (String lbl,int px,int qt, int pds){

super(lbl,px,qt);

poids = pds;

} }

(7)

Remarque: une classe abstraite peut posséder des méthodes concrètes ou abstraites; si une classe possède une méthode abstraite, toutes les classes dérivées devront implémenter cette méthode. Par exemple, si la méthode affiche était déclarée:

public abstract class Produit {

...

public abstract void affiche();

...

}

Notez que la méthode abstraite n'a pas de "corps" ; on dit qu'elle constitue une promesse.

Utilisation des classes abstraites.

Une classe abstraite est une classe qui ne peut être instanciée. Une classe abstraite est utilisée dans deux situations particulières:

1) Les sous-classes forment une couverture de la classe abstraite

Commentaires : Les personnels d'un lycée sont composés soit des enseignants des administratifs ou des personnels de services. Les trois sous-classes "couvrent" l'ensemble des personnels.

2) La classe abstraite ne contient pas suffisamment d'informations pour instancier un objet, autrement dit cette classe n'est présente que pour factoriser des propriétés. Il s'agit souvent de classe qui modélise un concept.

Commentaires: La classe courbe modélise plutôt un concept. Il existe d'autres courbes que les paraboles et hyperboles.

Une classe abstraite ne peut pas se trouver à la fin d'une hiérarchie de classe. Une classe abstraite doit avoir au moins une sous-classe.

(8)

Les interfaces

Exercice 1 : Nous devons concevoir une application qui gère les boissons (exemples : jus d’orange, whisky…).

Une boisson est comestible. Représentez un diagramme de classes.

Exercice 2 : Nous devons maintenant gérer des services (exemples : repas, nuits d’hotel…)

Il faut pouvoir facturer les services et les boissons. Pour cela nous allons regrouper sur un ticket de caisse les objets payants.

Il nous faudra donc créer un attribut dans la classe TicketDeCaisse qui est une collection d’objets payants.

Représenter le diagramme de classes.

0..1

Comestible Payant 0..*

Boisson Service

TicketDeCaisse

Une interface est une classe abstraite qui ne comporte que des méthodes abstraites ( sans corps ) ou des

constantes. Son but est de déclarer ( et non définir ) des comportements communs à un ensemble de sous classes.

Les « sous classes » d’une interface sont en fait des classes qui implémentent toutes les méthodes imposées par l’interface. Elles ont la responsabilité de décrire toutes les méthodes de l’interface.

Une classe pourra avoir (implémenter) plusieurs interfaces alors qu'une classe ne peut dériver que d'une seule classe.

Exercice 3 : On souhaite définier la notion de figure géométrique. Une figure géométrique peut être un rectangle, un carré, un cercle…

Nous allons utiliser une interface Figure avec 2 méthodes (calculAire et calculPerimetre).

Nous allons créer une classe concrète Rectangle qui réalise (implémente) l’interface Figure.

Représentez un diagramme de classes et coder les 2 classes.

Exemple : on souhaite définir la notion de figure géométrique

public interface Figure {

public double calculAire();

public double calculPerimetre();

}

public class Rectangle implements Figure { private double longueur ;

private double largeur ;

public Rectangle(double longueur, double largeur) { this.longueur = longueur;

this.largeur = largeur;

}

public double calculAire() { return this.longueur * this.largeur ; }

public double calculPerimetre() { return 2 * ( this.longueur + this.largeur) ; } }

public class TestFigure {

public static void main(String[] args) { Figure f1 = new Rectangle(1.43,2.65);

System.out.println(f1.calculAire());

}

(9)

Pourquoi utiliser des interfaces ? 4 raisons…

1) Pour définir un couplage faible entre les classes.

Ceci est un souci permanent dans la conception objet, cela permet de masquer l'implémentation d'une classe en proposant des collaborations au niveau des interfaces. Par exemple, la classe TicketDeCaisse n’a besoin de connaître que le prix des objets Payant.

2) Utiliser des interfaces proposées par Java afin de profiter de classes fonctionnelles.

Exemple:La classe Arrays de Java permet d'effectuer des traitements sur les tableaux. Ses méthodes static sort vont permettre de trier des objets Comparable.

- Comparable est une interface qui annonce une seule méthode:

public int compareTo(Object o)

Pour utiliser une méthode sort de la classe Arrays sur un tableau d'objets, il faut que la classe de ces objets implémente la méthode compareTo.

import java.util.*; // Pour la classe Arrays class Personne implements Comparable { //Interface private String nom;

private int solde;

Personne(String nom,int solde){

this.nom=nom;

this.solde=solde;

}

public int compareTo(Object o){ // définition de la méthode de Comparable Personne p = (Personne)o;

return solde - p.solde;

}

public void affiche(){

System.out.println(nom +" " + solde);

} }

class TestPersonne{

public static void main(String[] args){

Personne[] desPersonnes = new Personne[5];

desPersonnes[0] = new Personne("toto",200);

desPersonnes[1] = new Personne("titi",500);

desPersonnes[2] = new Personne("tintin",400);

Arrays.sort(desPersonnes);

for(int i =0;i<3;i++)

desPersonnes[i].affiche();

} }

Commentaires:

La classe Personne implémente l'interface Comparable, donc elle doit proposer une implémentation de la méthode compareTo; ici nous comparons les soldes. A noter que le paramètre de la méthode compareTo est de type Object - superClasse originaire - il nous faut caster - transtyper -ce paramètre en un objet de type Personne.

3) Définir des constantes utilisables dans les classes implémentant l'interface.

public interface MesConstantes{

public static final int PI=3.14; // Déclaration des constantes }

class A implements MesContantes{

// Les constantes de l'interface sont disponibles }

4) Permettre l’héritage multiple (interdit en java avec extends)

Références

Documents relatifs

Dilemme, dont la seule issue possible est d’installer une méthode evolue() dans la classe Ressource , tout en déclarant cette méthode « abstraite », c’est-à-dire sans

On constate qu’une classe abstraite (exemple BufferedReader) contient au moins une méthode abstraite (exemple : abstract void close()). Création d’un fichier

Par contre, un rectangle est une figure géométrique dont le calcul du périmètre et de la surface est connu, on peut alors implémenter ces méthodes qui sont très concrètes (pas

L’évaluation d’un circuit consiste, étant données se valeurs d’entrée, à déterminer sa valeur de sortie.. Travail

Toutefois, une classe abstraite peut implémenter une interface avec des méthodes abstraites qui seront donc finalement implémentées par les méthodes des classes réalisant

Une classe dérivée d’une classe non abstraite peut être déclarée abstraite et/ou contenir des méthodes abstraites... Java Classes et

Une fois cela fait, la classe fille aura accès aux membres de la classe de base, comme dans un héritage classique. Dans une classe abstraite, il est possible de définir des

• Parce qu’ils sont orientés objets, UML et Java ont des concepts en commun qui facilitent le mapping. – Classe, classe abstraite, interface,