• 20 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

Ce cours est en vidéo.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

J'ai tout compris !

Mis à jour le 12/10/2018

Utilisez le polymorphisme

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Dans le chapitre précédent, nous avons vu la spécialisation. Dans celui-ci, nous allons aborder la généralisation.

Entre  Product ,  Television  et  Fridge , cela fait beaucoup de types différents. Nous allons voir ici comment travailler avec tous ces types.

Généralisation

L'ArrayList  contenue dans  Bill  contient des  Product .

Va-t-il falloir ajouter deux autres  ArrayList  pour contenir nos  Television  et nos  Fridge  ?

Eh bien non ! Un objet  Television  ou  Fridge  est avant tout un objet de type  Product .

Nous pouvons donc sans problème faire :

public static void main(String[] args) {
    Product cafe = new Product("Philips HD7866/61", "Philips SENSEO Quadrante, Noir - 1 ou 2 tasses", 79.99);
    Television tv = new Television("TV Samsung UE49MU6292", "Smart TV LED incurvée 49\"", 599, 49, "LED");
    Fridge fridge = new Fridge("BEKO TSE 1042 F", "Réfrigérateur BEKO 130L - Classe A+ - blanc", 189, 130, false);
    
    Customer customer = new Customer("Juste Leblanc", "19 rue Germain Pilon, Paris");
    
    Bill bill = new Bill(customer);
    bill.addProduct(cafe, 1);
    bill.addProduct(tv, 1);
    bill.addProduct(fridge, 1);
}

Un objet  Television  peut ainsi être considéré comme un objet  Television , mais aussi comme un objet  Product . Cette action est appelée une généralisation.

Product tv = new Television("TV Samsung UE49MU6292", "Smart TV LED incurvée 49\"", 599, 49, "LED");

Television utilisée comme Produit

Vous comprenez mieux pourquoi une  ArrayList  ou une  Map  peuvent être déclarées comme ceci :

private Map<Product, Integer> products = new HashMap<Product, Integer>();

HashMap  est un enfant de  Map , on peut l’utiliser comme une  Map .

Mais alors, pourquoi utiliser la généralisation ici ?

Il existe de nombreux types de  Map  différents :  HashMap ,  ConcurrentHashMap ,  LinkedHashMap , etc.

Chacun a ses avantages et ses inconvénients, au niveau des performances. En fonction de la situation, il faut utiliser un type ou l’autre. Si, finalement,  HashMap  n’est pas le type le plus adapté pour  products , on peut facilement en changer.

Surcharge

Pour l’instant, dans la spécialisation, nous avons vu l’ajout de nouveaux comportements.

Nous avons aussi la possibilité de surcharger un comportement. Nous l’avons déjà fait avec les constructeurs. Un objet  Vehicle  nécessite des paramètres précis pour être construit. En créant  Car , nous avons ajouté des paramètres nécessaires au constructeur.

Donc  Car  est un  Vehicle , mais ne se crée pas de la même façon.

Vous pouvez faire exactement la même chose avec une méthode.

On va changer le comportement de  start  et de  stop  dans  Car , pour afficher :

System.out.println("Je suis " + modelName + " je consomme " + literPer100km + " au 100km et je démarre !" );
System.out.println("Je suis " + modelName + " j'arrête mon moteur " + motor);

On va utiliser le mot clé  @Override  pour faire cela :

public class Car extends Vehicle {
	...
	@Override
	public void start() {
    		System.out.println("Je suis " + modelName + " je consomme " + literPer100km + "l au 100km et je démarre !" );
	}

	@Override
	public void stop() {
    		System.out.println("Je suis " + modelName + " j'arrête mon moteur " + motor);	
	}
}

Ce code ne va pas fonctionner directement !  modelName  n’est pas accessible dans  Car. Il est  private  et donc accessible uniquement dans  Vehicle . Il existe une visibilité permettant à la classe et ses enfants d'y avoir accès :  protected.

public class Vehicle {
    	protected String modelName;
	...
}

Classe abstraite

À cette notion de surcharge est associée la notion de classe abstraite.

Finalement, nous pourrions nous dire qu'un véhicule n'existe pas forcément : il peut y avoir une voiture, un camion, un avion, mais pas un véhicule. Un véhicule est un concept abstrait, qui n'est pas suffisamment précis.

Ainsi, il faut garder ce concept de  Vehicle  dans notre application, mais aucun développeur ne doit pouvoir en instancier un. Il devra instancier Car, Boat, Truck, etc. Dans cette même logique, le code à l'intérieur des méthodes  start  et  stop  n'a plus de sens dans  Vehicle . Il sera forcément  @Override  dans les classes enfants.

Voilà comment représenter tout ça :

public abstract class Vehicle {
    protected String modelName;
    private String description;
    private String manufacturer;
    private int yeah;
    private String color;
    private int speed;
    private int[] dimensions = new int[3];
    private int weight;

    public Vehicle(String modelName, String description, String manufacturer, int yeah, String color, int speed, int[] dimensions, int weight) {
        this.modelName = modelName;
        this.description = description;
        this.manufacturer = manufacturer;
        this.yeah = yeah;
        this.color = color;
        this.speed = speed;
        this.dimensions = dimensions;
        this.weight = weight;
    }

    public abstract void start();

    public abstract void stop();
    
    ...
}

De cette façon, le code suivant ne peut plus fonctionner. Il y aura une erreur de compilation.

Vehicle vehicle = new Vehicle("Renault Super 5", ...

Toutes les classes qui héritent de Vehicle  devront forcément surcharger start  et  stop .

Erreur surcharge
Erreur surcharge

Gardez ces concepts en mémoire, nous allons les utiliser dès le prochain chapitre !

Exemple de certificat de réussite
Exemple de certificat de réussite