https://github.com/heig-vd-progim-course/heig-vd-progim2-course
Visualiser le contenu complet sur GitHub à cette adresse.
V. Guidoux, avec l'aide de GitHub Copilot.
Ce travail est sous licence CC BY-SA 4.0.
Cette présentation est un résumé du contenu complet disponible sur GitHub.
Pour plus de détails, consulter le contenu complet sur GitHub ou en cliquant sur l'en-tête de ce document.
extends
super
abstract
protected
final
Dans la session précédente, nous avons créé des classes simples avec des attributs directement accessibles (sans encapsulation).
Problèmes :
Encapsulation : protéger les données et contrôler leur accès.
Héritage : réutiliser du code et créer des hiérarchies de classes.
Protéger les données et contrôler leur accès
class BankAccount { public String owner; public double balance; }
BankAccount account = new BankAccount(); account.balance = -5000.0; // Solde négatif ! account.balance = 999999999; // Montant irréaliste !
Aucune protection : modifications directes non contrôlées.
public
private
class BankAccount { private String owner; private double balance; public void displayInfo() { System.out.println("Solde: " + balance + " CHF"); } } // ... dans une autre classe BankAccount account = new BankAccount(); account.balance = 1000.0; // ERREUR : balance est privé
class BankAccount { private String owner; private double balance; // Getters public String getOwner() { return owner; } public double getBalance() { return balance; } // Setters public void setOwner(String owner) { this.owner = owner; } public void setBalance(double balance) { this.balance = balance; } }
public void setBalance(double balance) { if (balance < 0) { System.out.println("Erreur: solde négatif."); return; } this.balance = balance; } public void withdraw(double amount) { if (amount > balance) { System.out.println("Erreur: solde insuffisant."); return; } balance -= amount; }
class Circle { private final double radius; public Circle(double radius) { this.radius = radius; } // Pas de setRadius() car radius est final }
Utile pour : constantes, identifiants uniques, valeurs qui ne doivent pas changer.
Réutiliser du code et créer des hiérarchies
class Car { private String brand; private String model; private int year; private int numberOfDoors; } class Motorcycle { private String brand; // Code dupliqué private String model; // Code dupliqué private int year; // Code dupliqué private boolean hasSidecar; }
class Vehicle { protected String brand; protected String model; protected int year; } class Car extends Vehicle { // Hérite de brand, model, year private int numberOfDoors; } class Motorcycle extends Vehicle { // Hérite de brand, model, year private boolean hasSidecar; }
L'héritage modélise une relation "est-un" (is-a) :
Attention : ne pas confondre avec "a-un" (has-a) :
class Animal { protected String name; protected int age; public void eat() { System.out.println(name + " mange."); } } class Dog extends Animal { private String breed; public void bark() { System.out.println(name + " aboie !"); } }
Dog hérite des attributs et méthodes de Animal.
Dog
Animal
Appeler le constructeur parent :
class Dog extends Animal { private String breed; public Dog(String name, int age, String breed) { super(name, age); // Appelle Animal(name, age) this.breed = breed; } }
super() doit être la première instruction du constructeur.
super()
class Parent { private String secret; // Non accessible aux sous-classes protected String family; // Accessible aux sous-classes public String forEveryone; // Accessible partout } class Child extends Parent { public void test() { // secret = "test"; // ERREUR family = "test"; // OK forEveryone = "test"; // OK } }
Une méthode abstraite n'a pas d'implémentation :
abstract class Shape { protected String color; public abstract double calculateArea(); // Pas de corps public void displayColor() { System.out.println("Couleur: " + color); } }
Les sous-classes doivent l'implémenter.
class Circle extends Shape { private double radius; @Override public double calculateArea() { return Math.PI * radius * radius; } } class Rectangle extends Shape { private double width, height; @Override public double calculateArea() { return width * height; } }
Chaque forme implémente le calcul d'aire différemment.
Une classe abstraite ne peut pas être instanciée :
abstract class Employee { protected String name; public abstract double calculateSalary(); } class FullTimeEmployee extends Employee { @Override public double calculateSalary() { return baseSalary; } } Employee e = new Employee(); // ERREUR ! FullTimeEmployee e = new FullTimeEmployee(); // OK
Sert de modèle pour les sous-classes.
Redéfinition (overriding) :
@Override
Surcharge (overloading) :
class Calculator { public int add(int a, int b) { return a + b; } // Surcharge public double add(double a, double b) { return a + b; } // Surcharge }
Sur une méthode : empêche la redéfinition dans les sous-classes.
class Parent { public final void criticalMethod() { // Ne peut pas être redéfinie } }
Sur une classe : empêche l'héritage.
public final class MathUtils { /* Aucune sous-classe possible */ }
Principes :
Documentation officielle :
Tutoriels :
Contenu complet sur GitHub.
Des questions sur l'encapsulation ou l'héritage ?
URLs