lever l’ambiguïté entre paramètre et attribut
public class Personne {
private String nom;
public void setNom(String nom) {
this.nom = nom;
}
}
Dans cet exemple, "this.nom
" fait référence à l'attribut de la classe, tandis que "nom
" tout seul fait référence au paramètre de la méthode.
pour qu’un objet se référence lui-même auprès d’un autre objet
public class Employe {
public void rejoindreEquipe(Equipe equipe) {
equipe.ajouterMembre(this);
}
}
Ici, "this
" est utilisé pour passer l'instance courante de l'Employe à la méthode ajouterMembre
de l'Equipe.
Pour qu’un constructeur en appelle un autre
public class Voiture {
private String marque;
private String modele;
private int annee;
public Voiture(String marque, String modele, int annee) {
this.marque = marque;
this.modele = modele;
this.annee = annee;
}
public Voiture(String marque, String modele) {
this(marque, modele, 2023); // Appel au constructeur à 3 paramètres
}
}
appeler le super constructeur
public class Animal {
protected String nom;
protected int age;
public Animal(String nom, int age) {
this.nom = nom;
this.age = age;
}
}
public class Chien extends Animal {
private String race;
public Chien(String nom, int age, String race) {
super(nom, age); // Appel du constructeur de la classe parente
this.race = race;
}
public void afficherDetails() {
System.out.println("Nom: " + nom + ", Age: " + age + ", Race: " + race);
}
}
Dans cet exemple, le constructeur de la classe "Chien
" utilise "super(nom, age)
" pour appeler le constructeur de la classe parente "Animal
" et initialiser les attributs hérités.
appeler la méthode, redéfinie dans la classe courante
public class Forme {
public void dessiner() {
System.out.println("Dessin d'une forme générique");
}
}
public class Cercle extends Forme {
@Override
public void dessiner() {
super.dessiner(); // Appel de la méthode de la classe parente
System.out.println("Dessin d'un cercle");
}
public void dessinerAvecDetails() {
System.out.println("Préparation du dessin du cercle");
super.dessiner(); // Appel de la méthode de la classe parente
System.out.println("Ajout des détails spécifiques au cercle");
}
}
Dans cet exemple, la classe "Cercle
" redéfinit la méthode "dessiner
". Dans sa propre implémentation de "dessiner
", elle utilise "super.dessiner()
" pour appeler d'abord la méthode de la classe parente, puis ajoute son propre comportement.
De plus, la méthode "dessinerAvecDetails
" montre comment on peut utiliser "super.dessiner()" dans un contexte différent pour réutiliser le comportement de la classe parente.
Devant un nom de classe : pas possible d’étendre la classe
public final class MathUtils {
public static double PI = 3.14159;
public static int additionner(int a, int b) {
return a + b;
}
}
// Ceci provoquera une erreur de compilation
// public class MathUtilsEtendu extends MathUtils {}
Dans cet exemple, MathUtils
est une classe finale. Toute tentative d'en hériter (comme avec la classe commentée MathUtilsEtendu
) résulterait en une erreur de compilation.
Devant un nom de méthode : pas possible de la redéfinir dans les sous-classes
public class Animal {
public final void respirer() {
System.out.println("L'animal respire");
}
public void manger() {
System.out.println("L'animal mange");
}
}
public class Chien extends Animal {
// Ceci est autorisé car manger() n'est pas final
@Override
public void manger() {
System.out.println("Le chien mange des croquettes");
}
// Ceci provoquerait une erreur de compilation
// @Override
// public void respirer() {
// System.out.println("Le chien respire");
// }
}
Ici, la méthode respirer()
de la classe Animal
est déclarée final
. La classe Chien
ne peut pas la redéfinir, mais peut redéfinir la méthode manger()
qui n'est pas finale.
Devant un nom d’attribut : attribut constant
public class Cercle {
public final double PI = 3.14159;
private double rayon;
public Cercle(double rayon) {
this.rayon = rayon;
}
public double calculerSurface() {
return PI * rayon * rayon;
}
}
public class TestCercle {
public static void main(String[] args) {
Cercle cercle = new Cercle(5);
System.out.println("Surface du cercle : " + cercle.calculerSurface());
// Ceci provoquerait une erreur de compilation
// cercle.PI = 3.14;
}
}
Dans cet exemple, PI
est déclaré comme un attribut final
. Sa valeur ne peut pas être modifiée après l'initialisation. Toute tentative de modification (comme dans la ligne commentée) résulterait en une erreur de compilation.
Devant un nom de méthode : celle-ci peut être appelée sans avoir besoin d’une instance
public class MathUtils {
public static int additionner(int a, int b) {
return a + b;
}
public static double calculerAireCercle(double rayon) {
return Math.PI * rayon * rayon;
}
}
public class TestMathUtils {
public static void main(String[] args) {
// Appel des méthodes statiques sans créer d'instance de MathUtils
int somme = MathUtils.additionner(5, 3);
System.out.println("5 + 3 = " + somme);
double aire = MathUtils.calculerAireCercle(2.5);
System.out.println("L'aire d'un cercle de rayon 2.5 est : " + aire);
}
}
Dans cet exemple, les méthodes additionner
et calculerAireCercle
sont statiques. Elles peuvent être appelées directement sur la classe MathUtils
sans avoir besoin de créer une instance de cette classe.
Devant un nom d’attribut : celui-ci existe en un seul exemplaire quel que soit le nombre d’instances crées. ⇒ partage en mémoire
public class Compteur {
private static int nombreInstances = 0;
private int id;
public Compteur() {
nombreInstances++;
this.id = nombreInstances;
}
public int getId() {
return this.id;
}
public static int getNombreInstances() {
return nombreInstances;
}
}
public class TestCompteur {
public static void main(String[] args) {
System.out.println("Nombre d'instances au début : " + Compteur.getNombreInstances());
Compteur c1 = new Compteur();
System.out.println("Après création de c1 : " + Compteur.getNombreInstances());
System.out.println("ID de c1 : " + c1.getId());
Compteur c2 = new Compteur();
System.out.println("Après création de c2 : " + Compteur.getNombreInstances());
System.out.println("ID de c2 : " + c2.getId());
Compteur c3 = new Compteur();
System.out.println("Après création de c3 : " + Compteur.getNombreInstances());
System.out.println("ID de c3 : " + c3.getId());
}
}
Dans cet exemple :
nombreInstances
est un attribut statique. Il est partagé par toutes les instances de la classe Compteur
.Compteur
est créé, nombreInstances
est incrémenté.getNombreInstances()
permet d'accéder à la valeur de nombreInstances
sans avoir besoin d'une instance de Compteur
.id
non-statique, qui est initialisé avec la valeur courante de nombreInstances
.L'exécution de ce code produira une sortie similaire à ceci :
Nombre d'instances au début : 0
Après création de c1 : 1
ID de c1 : 1
Après création de c2 : 2
ID de c2 : 2
Après création de c3 : 3
ID de c3 : 3
Syntaxe :
nom_variable instanceof nom_classe
<aside> 😡
Aucune autre syntaxe possible !!!
</aside>
instanceof
Ce mot-clé n’est utile que lors de l’exécution. Il est une hérésie de la POO et peut toujours être évité MAIS parfois, instanceof
évite d’écrire beaucoup de code pas très utile.