Download Programmation java orienté objet and more Exercises Java Programming in PDF only on Docsity! Plan Problématiques abordées : I conception POO, héritage, classes abstraites (prix, affichage) I affichage polymorphique I interfaces I copie polymorphique Le problème I Les montres sont des produits (que l’on peut vendre : ont un prix) I Les montres ont un mécanisme de base et sont constituées de différents accessoires (boîtier, bracelet, ...) I Les produits ont un prix dont le calcul peut varier, à partir d’une valeur de base I Tous les produits sont « affichables », chacun à sa façon I Les mécanismes et accessoires de montre sont aussi des produits (on pourrait en acheter séparément) I Il existe trois sortes de mécanismes : analogiques (montre à aiguilles), digitaux et doubles. I Pour les mécanismes doubles, on supposera ici qu’ils n’indiquent qu’une seule heure, mais se comportent sinon à la fois comme des mécanismes analogiques et comme des mécanismes digitaux Hiérarchie de classes Produit Accessoire Montre Boitier Bracelet Fermoir Vitre MecanismeAnalogique MecanismeDigital MecanismeDouble Mecanisme Du problème au premier code I Les montres sont des produits I Les montres ont un mécanisme et sont constituées de différents accessoires I Les produits ont un prix dont le calcul peut varier, à partir d’une valeur de base I Tous les produits sont « affichables », chacun à sa façon I Les mécanismes et accessoires sont aussi des produits I Il existe trois sortes de mécanismes : analogiques, digitaux et doubles class Produit { } // ========================================== class Montre extends Produit { } // ========================================== class Montres { public static void main(String args[]) {} } Du problème au premier code I Les montres sont des produits I Les montres ont un mécanisme et sont constituées de différents accessoires I Les produits ont un prix dont le calcul peut varier, à partir d’une valeur de base I Tous les produits sont « affichables », chacun à sa façon I Les mécanismes et accessoires sont aussi des produits I Il existe trois sortes de mécanismes : analogiques, digitaux et doubles import java.util.ArrayList; // ... // ========================================== class Accessoire { } // ========================================== class Mecanisme { } // ========================================== class Montre extends Produit { private Mecanisme coeur; private ArrayList<Accessoire> accessoires; } Du problème au premier code I Les montres sont des produits I Les montres ont un mécanisme et sont constituées de différents accessoires I Les produits ont un prix dont le calcul peut varier, à partir d’une valeur de base I Tous les produits sont « affichables », chacun à sa façon I Les mécanismes et accessoires sont aussi des produits I Il existe trois sortes de mécanismes : analogiques, digitaux et doubles class Produit { private double prix; } // ... Du problème au premier code I Les montres sont des produits I Les montres ont un mécanisme et sont constituées de différents accessoires I Les produits ont un prix dont le calcul peut varier, à partir d’une valeur de base I Tous les produits sont « affichables », chacun à sa façon I Les mécanismes et accessoires sont aussi des produits I Il existe trois sortes de mécanismes : analogiques, digitaux et doubles class Produit { private double valeur; public double prix() { return valeur; } } // ... Du problème au premier code I Les montres sont des produits I Les montres ont un mécanisme et sont constituées de différents accessoires I Les produits ont un prix dont le calcul peut varier, à partir d’une valeur de base I Tous les produits sont « affichables », chacun à sa façon I Les mécanismes et accessoires sont aussi des produits I Il existe trois sortes de mécanismes : analogiques, digitaux et doubles class Produit { private double valeur; public virtual double prix() { return valeur; } public String toString() { //.. } } // ... Finalisation de la classe Produit Supposons enfin que : I un produit n’existe pas en tant que tel : c’est une abstraction I l’on fixe la valeur de base d’un produit au départ et que l’on ne puisse pas en changer I un produit ait par défaut une valeur de base nulle La classe Produit abstract class Produit { private final double valeur; public Produit(double uneValeur) { valeur = uneValeur; } public Produit() { valeur = 0.0; } public double prix() { return valeur; } public String toString() { return Double.toString(prix()); } } Ajout d’accessoires (aux Montres) Rappel : class Montre extends Produit { private Mecanisme coeur; private ArrayList<Accessoire> accessoires; } On souhaite ajouter des accessoires . Par exemple : montre.ajouter(new Bracelet(...)); Ajout d’accessoires (aux Montres) class Montre extends Produit { private Mecanisme coeur; private ArrayList<Accessoire> accessoires; public void ajouter(Accessoire accessoire) { accessoires.add(accessoire); // nous reviendrons sur ce point } } Finalisation d’une première version Essayons maintenant d’avoir une première version opérationnelle de notre code, pour le moment : I sans tous les mécanismes I sans copie des montres Pour cela, il nous faut encore : I quelques accessoires I terminer la classe Montre I un exemple d’utilisation dans une méthode main() Quelques accessoires Décidons par exemple que les accessoires : I ont un nom et une valeur de base fixés au départ (sans valeur par défaut) I s’affichent en indiquant leur nom et leur prix I que leur prix est celui d’un produit usuel abstract class Accessoire extends Produit { private final String nom; public Accessoire(String unNom, double valeurDeBase) { super(valeurDeBase); nom = unNom; } } Quelques accessoires Décidons par exemple que les accessoires : I ont un nom et une valeur de base fixés au départ (sans valeur par défaut) I s’affichent en indiquant leur nom et leur prix I que leur prix est celui d’un produit usuel abstract class Accessoire extends Produit { private final String nom; public Accessoire(String unNom, double valeurDeBase) { super(valeurDeBase); nom = unNom; } @Override public String toString() { String result = nom + " coûtant "; result += super.toString(); return result; } } Quelques accessoires Décidons par exemple que les accessoires : I ont un nom et une valeur de base fixés au départ (sans valeur par défaut) I s’affichent en indiquant leur nom et leur prix I que leur prix est celui d’un produit usuel Quelques accessoires class Bracelet extends Accessoire { public Bracelet(String unNom, double valeurDeBase) { super("bracelet " + unNom, valeurDeBase); } } //------------------------------------------------------ class Fermoir extends Accessoire { public Fermoir(String unNom, double valeurDeBase) { super("fermoir " + unNom, valeurDeBase); } } //... Finalisation des Montres Pour finaliser la classe Montre (mais sans mécanisme) : I contentons nous pour l’heure d’un constructeur par défaut I décidons d’un calcul de prix : somme des prix des accessoires I décidons d’un affichage : Une montre composée de : * bracelet cuir coûtant 54 * fermoir acier coûtant 12.5 * etc. ==> Prix total : 147.9 class Montre extends Produit { private Mecanisme coeur; private ArrayList<Accessoire> accessoires; public Montre() { accessoires = new ArrayList<Accessoire>(); } // ... } Constructeurs des sous-classes class MecanismeAnalogique extends Mecanisme { private int date; public MecanismeAnalogique(double valeurDeBase, String uneHeure, int uneDate) { super (valeurDeBase, uneHeure); date = uneDate; } } class MecanismeDigital extends Mecanisme { private String reveil; public MecanismeDigital(double valeurDeBase, String uneHeure, String heureRev) { super(valeurDeBase, uneHeure); reveil = heureRev; } } // ... Constructeurs des sous-classes (suite) class MecanismeDouble extends MecanismeAnalogique { private String reveil; public MecanismeDouble(double valeurDeBase, String uneHeure, int uneDate, String heureReveil) { super(valeurDeBase, uneHeure, uneDate); reveil = heureReveil; } } Gestion de la valeur par défaut de la super-classe class MecanismeDouble extends MecanismeAnalogique implements ReveilDigital { public MecanismeDouble(double valeurDeBase, String uneHeure, int uneDate, String heureReveil) { super(valeurDeBase, uneHeure, uneDate); reveil = heureReveil; } // gestion propre de la valeur par défaut de l'heure (super-classe) public MecanismeDouble(double valeurDeBase, int uneDate, String heureReveil) { super(valeurDeBase, uneDate); reveil = heureReveil; } } Gestion de la valeur par défaut de la super-classe public MecanismeDouble(double valeurDeBase, String uneHeure, int uneDate, String heureReveil) { super(valeurDeBase, uneHeure, uneDate); reveil = heureReveil; } public // gestion propre de la valeur par défaut de l'heure (super-classe) MecanismeDouble(double valeurDeBase, int uneDate, String heureReveil) { super(valeurDeBase, uneDate); reveil = heureReveil; } Construction d’une Montre Complétons maintenant nos constructeurs pour la classe Montre : class Montre extends Produit { private Mecanisme coeur; private ArrayList<Accessoire> accessoires; //.. public Montre(Mecanisme depart) { coeur = depart; // nous y reviendrons accessoires = new ArrayList<Accessoire>(); } //.. } Affichage des Mecanismes Supposons que l’on veuille : I que tous les mécanismes s’affichent suivant le même schéma, imposé et non modifiable Par exemple : affichage du type de mécanisme, suivi d’un affichage du cadran (heure, date, heure de réveil, ...), suivi du prix I mais que chaque partie de ce schéma soit adaptable I offrir une version par défaut, utilisable dans les sous-classes, de l’affichage du cadran (par exemple affichage de l’heure) I imposer la redéfinition de l’affichage du type de mécanisme + Comment faire ? Affichage des Mecanismes : niveau général abstract class Mecanisme extends Produit { //... // Tous les mécanismes DOIVENT s'afficher comme ceci public final String toString() { String result = "mécanisme "; result += toStringType(); result += " (affichage : "; result += toStringCadran(); result += "), prix : "; result += super.toString(); return result; } // on veut offrir la version par défaut aux sous-classes et aux classes // du même paquetage. Par défaut, on affiche juste l'heure. protected String toStringCadran() { return heure; } // Un mécanisme, ici à ce niveau, est abstrait (= classe abstraite) protected abstract String toStringType(); } Affichage des Mecanismes : sous-classes class MecanismeDigital extends Mecanisme { //.. @Override protected String toStringType() { return "digital"; } @Override protected String toStringCadran() { // On affiche l'heure (façon de base)... // ...et en plus l'heure de réveil. return super.toStringCadran() + ", " + toStringReveil(); } protected String toStringReveil() { return " réveil " + reveil; } } Affichage des Mecanismes : sous-classes class MecanismeDouble extends MecanismeAnalogique { //... @Override protected String toStringCadran() { // Par exemple... String result = "sur l'écran : "; result += super.toStringCadran(); result += ", sous les aiguilles : "; result += toStringReveil(); return result; } @Override protected String toStringType() { return "double"; } // propres aux mécanismes digitaux protected String toStringReveil() { return " réveil " + reveil; } } Affichage des Mecanismes : sous-classes Il serait bien : I d’imposer aux mécanismes ayant (aussi) un comportement digital d’implémenter la méthode toStringReveil ; I d’expliciter le lien entre les mécanismes ayant un comportement digital. Hiérarchie de classe Produit Accessoire Montre Boitier Bracelet Fermoir Vitre MecanismeAnalogique MecanismeDigital MecanismeDoubleMecanisme interface ReveilDigital Révision de la hiérarchie //====================================================================== interface ReveilDigital { String toStringReveil(); } //====================================================================== class MecanismeDigital extends Mecanisme implements ReveilDigital { //... // propres aux mécanismes digitaux public String toStringReveil() { return " réveil " + reveil; } } //====================================================================== class MecanismeDouble extends MecanismeAnalogique implements ReveilDigital { //.. // propres aux mécanismes digitaux public String toStringReveil() { return " réveil " + reveil; } } Copie polymorphique public Montre(Montre autre) { super(autre); coeur = autre.coeur.copie(); accessoires = new ArrayList<Accessoire>(); for (Accessoire acc : autre.accessoires) { accessoires.add(acc.copie()); } } Copie polymorphique ArrayList<Accessoire> accessoires; // ... accessoires.add(acc.copie()); abstract class Accessoire extends Produit { //... // copie polymorphique d'Accessoire public abstract Accessoire copie(); //.. } //---------------------------------------------- class Bracelet extends Accessoire { //.. public Bracelet(Bracelet autre) { super(autre); } // copie polymorphique de Bracelet @Override public Bracelet copie(){ return new Bracelet(this); } } Autre copie class Montre extends Produit { //... public Montre(Mecanisme depart) { coeur = depart.copie(); accessoires = new ArrayList<Accessoire>(); } //... } La méthode clone Les traitements de copie, tels que ceux montrés précedemment, sont usuellement fait en java au moyen de la redéfinition de la méthode clone héritée de Object Les classes redéfinissant clone doivent implémenter l’interface Cloneable. Test : un exemple de main() public static void main(String[] args) { // le reste comme avant // Nous faisons une copie de la montre m Montre m2 = new Montre(m); System.out.println("Montre m2 :"); m2.afficher(); } Le code complet à ce stade (415 lignes) peut être téléchargé sur le site du cours : https://d396qusza40orc.cloudfront.net/java-fr/complements/Montres.java