CodeGym/Blog Java/Random-FR/Concepts POO en Java
Auteur
Alex Vypirailenko
Java Developer at Toshiba Global Commerce Solutions

Concepts POO en Java

Publié dans le groupe Random-FR
membres
L'une des plus grandes forces de Java est la programmation orientée objet (POO). C'est la raison pour laquelle ce langage est devenu si populaire et convient parfaitement aux projets de toute taille. Qu'est-ce que la programmation orientée objet ? Ce n'est pas de la magie, mais cela peut sembler magique si vous vous y mettez vraiment. La POO concerne la façon de créer votre logiciel. C'est un concept, ou plutôt un ensemble de concepts oop en Java, qui vous permettent de créer des interactions et des relations spécifiques entre des objets Java afin de développer et d'utiliser efficacement des logiciels. Concepts POO en Java - 1La POO classique comprend 3 + 1 concepts principaux. Commençons par les classiques.

L'object

Les objets Java ainsi que les objets du monde réel ont deux caractéristiques : l'état et le comportement.

Par exemple, un objet humain a un état (nom, sexe, dormir ou non…) et un comportement (étudie Java, marche, parle…). Tout objet Java stocke son état dans des champs et expose son comportement via des méthodes.

Encapsulation

L'encapsulation des données cache les données internes du monde extérieur et n'y accède que par des méthodes exposées publiquement. Qu'est-ce que cela signifie? Quelles données ? Se cacher de qui ? Masquer signifie restreindre l'accès direct aux données membres (champs) d'une classe.

Comment ça marche en Java :

  1. Les champs sont rendus privés
  2. Chaque champ d'une classe reçoit deux méthodes spéciales : un getter et un setter. Les méthodes getter renvoient la valeur du champ. Les méthodes setter vous permettent de modifier la valeur du champ de manière indirecte mais autorisée.

Exemple d'encapsulation en code Java :

public class Student {
private int age;
private String name;

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

public class Test{
public static void main(String[] args) {
Student firstStudent = new Student();
firstStudent.setName("John");
// The name field is private, so you can no longer do this:  firstStudent.name = "John";
}
}

Pourquoi utiliser l'encapsulation ?

La raison principale est de faciliter la modification de votre code. Imaginez que vous ayez une application pour une école de hockey et qu'il y ait une classe HockeyStudent avec deux champs qui stockent le nom et l'âge de l'élève lorsqu'il s'est inscrit à l'école. Quelque chose comme ça:
public class HockeyStudent {
public String name;
public  int ageOfEnrollment;
}
Le champ ageOfEnrollment est public, pas de getters ni de setters… Cette classe est utilisée par de nombreuses autres classes, et tout allait bien jusqu'à ce qu'un développeur décide qu'un seul champ int n'était pas suffisant. Certains joueurs de hockey d'une cohorte ont presque un an de plus que leurs pairs, il serait donc plus pratique de les diviser en deux groupes selon le mois de leur naissance. Ainsi, le champ ageOfEnrollment doit être remplacé par un tableau int (int[][]) : le premier nombre correspond aux années complètes et le second aux mois. Vous devez maintenant refactoriser tout le code qui utilise la classe Student ! Mais si votre ageOfEnrollmentle champ est privé et vous avez des getters et des setters, alors tout est plus facile. Si l'exigence de définition de l'âge d'un élève change, mettez simplement à jour la logique dans la méthode setAgeOfEnrollment() et vos classes pourront continuer à utiliser Student sans aucun problème ! Cet exemple est quelque peu artificiel, mais j'espère qu'il explique pourquoi l'encapsulation est une excellente idée.

Héritage

Ce principe est plus facile à comprendre même sans aucune expérience pratique. Ne vous répétez pas (DRY) pourrait être la devise du concept d'héritage. L'héritage vous permet de créer une classe enfant qui hérite des champs et des méthodes de la classe parent sans les redéfinir. Bien sûr, vous pouvez remplacer les champs et les méthodes de la classe parent dans la classe enfant, mais ce n'est pas une nécessité. De plus, vous pouvez ajouter de nouveaux états et comportements dans la classe enfant. Les classes parentes sont parfois appelées superclasses ou classes de base, et les classes enfants sont appelées sous-classes. Le mot clé extend de Java est utilisé pour implémenter le principe d'héritage dans le code.

Comment ça marche en Java :

  1. Créez la classe mère.
  2. Créez la classe enfant à l'aide du mot clé extend .
  3. Dans le constructeur de la classe Child, utilisez la méthode super(parentField1, parentField2, ...) pour définir les champs du parent.

Un constructeur est une méthode spéciale utilisée pour initialiser un objet nouvellement créé. Un constructeur porte le même nom que son nom de classe. Il existe deux types de constructeurs : par défaut (constructeur sans argument) et constructeur paramétré. Une classe doit avoir au moins un constructeur (elle a le constructeur par défaut si aucun autre constructeur n'a été défini) et elle peut en avoir beaucoup.

Chaque fois que vous créez un nouvel objet, vous appelez son constructeur. Dans l'exemple ci-dessus, vous faites cela dans cette ligne :

Student firstStudent = new Student();

Vous utilisez le mot clé new pour appeler le constructeur par défaut de la classe Student : tudent() .

Certaines règles:

  1. Une classe ne peut avoir qu'un seul parent.
  2. Une classe parent peut avoir plusieurs classes enfant.
  3. Une classe enfant peut avoir ses propres classes enfant.

Exemple d'héritage en code Java

Créons une classe Phone .
public class Phone {
    int price;
    double weight;

// Constructor
public Phone(int price, double weight) {
        this.price = price;
        this.weight = weight;
    }

    void orderPhone(){
        System.out.println("Ordering phone...");
    }
}
Bien sûr, il existe différents types de téléphones, créons donc deux classes enfants : une pour les téléphones Android et une seconde pour les iPhones. Ensuite, nous ajouterons des champs et des méthodes que le parent n'a pas. Et nous utiliserons super() pour appeler les constructeurs afin d'initialiser les champs que la classe parent possède.

Exemple d'héritage en Java

public class Android extends Phone {

// Some new fields
String androidVersion;
int screenSize;

    String secretDeviceCode;

// Constructor
    public Android(int price, double weight, String androidVersion, int screenSize, String secretDeviceCode) {
        super(price, weight); // Android inherits Phone’s fields

        //this - reference to the current object
        //super - reference to the parent object

        this.androidVersion = androidVersion;
        this.screenSize = screenSize;
        this.secretDeviceCode = secretDeviceCode;
    }

	// New Android-specific method, does not exist in the Phone class
    void installNewAndroidVersion() {
        System.out.println("installNewAndroidVersion invoked...");

    }

}

public class IPhone extends Phone {

    boolean fingerPrint;

    public IPhone(int price, double weight, boolean fingerPrint) {
        super(price, weight);
        System.out.println("IPhone constructor was invoked...");
        this.fingerPrint = fingerPrint;
    }

    void deleteIPhoneFromDb() {
        System.out.println("deleteIPhoneFromDb invoked...");
    }

@Override // This is about polymorphism, see below
void orderPhone(){
        System.out.println("Ordering my new iPhone and deleting the old one...");
    }
}
Donc, pour répéter : en Java, l'héritage vous permet d'étendre une classe avec des classes enfants qui héritent des champs et des méthodes de la classe parent. C'est un excellent moyen d'atteindre la réutilisabilité du code.

Polymorphisme

Le polymorphisme est la capacité d'un objet à se transformer, à prendre différentes formes ou plutôt à agir de différentes manières. En Java, le polymorphisme se produit généralement lorsqu'une référence de classe parent est utilisée pour faire référence à un objet de classe enfant.

Qu'est-ce que cela signifie et comment cela fonctionne en Java :

Qu'est-ce que le polymorphisme en Java ? En général, cela signifie que vous pouvez utiliser le même nom de méthode à des fins différentes. Il existe deux types de polymorphisme en Java : le remplacement de méthode (polymorphisme dynamique) et la surcharge de méthode (polymorphisme statique).

Remplacer la méthode

Vous pouvez remplacer la méthode d'une classe parent dans une classe enfant, la forçant à fonctionner différemment. Créons une classe parent Musician avec une méthode play() .

Exemple de polymorphisme en code Java

public class Musician {
    String name;
    int age;

    // Default constructor
    public Musician() {
    }

    // Parameterized constructor
    public Musician(String name, int age) {
        this.name = name;
        this.age = age;
    }

    void play() {
        System.out.println("I am playing my instrument...");
    }
}
Différents musiciens utilisent différents instruments. Créons deux classes enfants : Pianist et Violinist . Grâce au polymorphisme, chacun exécutera sa propre version de la méthode play() . Lors du remplacement, vous pouvez utiliser l' annotation @Override , mais ce n'est pas nécessaire.
public class Pianist extends Musician {

    String favoritePianoType;

    public Pianist(String name, int age, String favoritePianoType) {
        super(name, age);
        this.favoritePianoType = favoritePianoType;
    }


    @Override
void play(){
        System.out.println("I am playing the piano...");
    }
}
Le violoniste peut être soliste ou membre d'un orchestre. Prenons cela en considération lors de la redéfinition de notre méthode play() .
public class Violinist extends Musician {
    boolean isSoloist;

public Violinist(String name, int age, boolean isSoloist) {
            super(name, age);
            this.isSoloist = isSoloist;
        }


    @Override
void play(){
if (isSoloist)
        System.out.println("I am playing the violin solo...");
else
System.out.println("I am playing the violin in an orchestra...");

    }
}
Créons une classe Demo , dans laquelle nous allons créer trois objets, une instance de chacune des classes précédemment créées. Nous verrons quels résultats nous obtenons.
public class Demo {
  public static void main(String[] args) {
  Musician musician = new Musician();
  Violinist violinist = new Violinist("John", 32, true);
  Pianist pianist = new Pianist("Glen", 30, "Acoustic");

  System.out.println("Musician said:");
  musician.play();
  System.out.println("Violinist said:");
  violinist.play();
  System.out.println("Pianist said:");
  pianist.play();
    }
}
Voici ce que nous obtenons :
Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo…
Pianist said:
I am playing the piano...
Chaque violoniste et pianiste est un musicien, mais tous les musiciens ne sont pas altiste ou pianiste. Cela signifie que vous pouvez utiliser la méthode de jeu du musicien si vous n'avez pas besoin d'en créer une nouvelle. Ou vous pouvez appeler la méthode du parent depuis l'enfant en utilisant le super mot-clé. Faisons cela dans le code de Pianist :
public class Pianist extends Musician {

    String favoritePianoType;

    @Override
    void play(){
        super.play();
        System.out.println("I am playing the piano...");
    }
}
Appelons maintenant notre méthode main() dans la classe Demo . Voici le résultat :
Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo...
Pianist said:
I am playing my instrument...
I am playing the piano...

Surcharge de méthode

La surcharge de méthodes consiste à utiliser différentes méthodes portant le même nom dans la même classe. Ils doivent être différents en termes de nombre, d'ordre ou de types de leurs paramètres. Supposons qu'un pianiste puisse jouer d'un piano acoustique et d'un piano électrique. Pour jouer de l'électrique, le musicien a besoin d'électricité. Créons deux méthodes play() différentes . Le premier sans paramètres, pour un piano acoustique, et le second avec un paramètre qui indique si l'électricité est disponible.
public class Pianist extends Musician {

    String name;
    int age;
    String favoritePianoType;

    @Override
    void play(){
        super.play();
        System.out.println("I am playing the piano...");
    }
    void play(boolean isElectricity){
        if (isElectricity) {
            System.out.println("The electricity is on.");
            System.out.println("I am playing the piano...");
        }
        else System.out.println("I can't play this without electricity.");
    }
}
Au fait, vous pouvez utiliser la première méthode play() dans la seconde méthode play(boolean) de cette manière :
void play(boolean isElectricity){
        if (isElectricity) {
            System.out.println("The electricity is on.");
            play();
        }
        else System.out.println("I can't play this without electricity.");
    }
Ajoutons quelques lignes à notre classe Demo pour démontrer notre surcharge :
public class Demo {
    public static void main(String[] args) {

        Musician musician = new Musician();
        Violinist violinist = new Violinist("John", 23, true);
        Pianist pianist = new Pianist("Glen", 30, "Acoustic");

        System.out.println("Musician said:");
        musician.play();
        System.out.println("Violinist said:");
        violinist.play();
        System.out.println("Pianist said:");
        pianist.play();
        System.out.println("The pianist will now try the electric piano:");
        pianist.play(true);
        System.out.println("The electricity has been shut off. Now when trying the electric piano, the pianist says:");
        pianist.play(false);
    }
}
Voici le résultat :
Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo...
Pianist said:
I am playing my instrument...
I am playing the piano...
The pianist will now try the electric piano:
The electricity is on.
I am playing my instrument...
I am playing the piano...
The electricity has been shut off. Now when trying the electric piano, the pianist says:
I can't play this without electricity.
Java sait quelle méthode doit être utilisée en fonction de ses paramètres et du type d'objet. C'est le polymorphisme.

Abstraction

Lorsque nous définissons une classe, nous essayons de construire un modèle de quelque chose. Par exemple, supposons que nous écrivions un jeu vidéo appelé MyRacer avec différentes voitures de course. Un joueur peut en choisir un, puis le mettre à jour plus tard ou en acheter un autre. Alors… Qu'est-ce qu'une voiture ? Une voiture est une chose assez compliquée, mais si nous essayons de créer un jeu vidéo de course (par opposition à un simulateur de conduite), nous n'avons pas besoin de décrire les milliers d'engrenages et de joints qu'elle contient. Nous avons besoin de son modèle, de sa vitesse de pointe, de ses caractéristiques de maniabilité, de son prix, de sa couleur… Et c'est peut-être suffisant. C'est le modèle d'une voiture pour notre jeu. Plus tard dans MyRacer 2, supposons que nous décidions d'ajouter des pneus qui affectent la tenue de route sur la route. Ici, le modèle est différent, car nous avons ajouté plus de détails. Laisser' s définissent l'abstraction de données comme le processus consistant à identifier uniquement les caractéristiques importantes (ou nécessaires) d'un objet et à ignorer tous les détails non pertinents. Il existe différents niveaux d'abstraction. Par exemple, si vous êtes un passager dans un bus, vous devez savoir à quoi ressemble votre bus et où il va, mais vous n'avez pas besoin de savoir comment le conduire. Si vous êtes chauffeur de bus, vous n'avez pas besoin de savoir comment créer un nouveau bus, il vous suffit de savoir comment le conduire. Mais si vous êtes un fabricant de bus, vous devez passer à un niveau d'abstraction inférieur, car les détails de la conception du bus sont très importants pour vous. J'espère que tu comprends ce que je veux dire. vous devez savoir à quoi ressemble votre bus et où il va, mais vous n'avez pas besoin de savoir comment le conduire. Si vous êtes chauffeur de bus, vous n'avez pas besoin de savoir comment créer un nouveau bus, il vous suffit de savoir comment le conduire. Mais si vous êtes un fabricant de bus, vous devez passer à un niveau d'abstraction inférieur, car les détails de la conception du bus sont très importants pour vous. J'espère que tu comprends ce que je veux dire. vous devez savoir à quoi ressemble votre bus et où il va, mais vous n'avez pas besoin de savoir comment le conduire. Si vous êtes chauffeur de bus, vous n'avez pas besoin de savoir comment créer un nouveau bus, il vous suffit de savoir comment le conduire. Mais si vous êtes un fabricant de bus, vous devez passer à un niveau d'abstraction inférieur, car les détails de la conception du bus sont très importants pour vous. J'espère que tu comprends ce que je veux dire.

Comment ça marche en Java :

Construisons quatre niveaux d'abstraction en Java, ou plutôt en POO — du plus bas (le plus spécifique) au plus haut (le plus abstrait).
  1. Le niveau d'abstraction le plus bas est un objet spécifique. C'est une entité avec un ensemble de caractéristiques qui appartiennent à une classe spécifique. Il a des valeurs de champ spécifiques

  2. Un modèle de création d'objets est une classe. C'est une description d'un ensemble d'objets avec des propriétés et une structure interne similaires.

  3. Une classe abstraite est une description abstraite des caractéristiques d'un ensemble de classes (elle agit comme un modèle pour l'héritage par d'autres classes). Il a un haut niveau d'abstraction, il est donc impossible de créer des objets directement à partir d'une classe abstraite. Seules les classes enfants des classes abstraites peuvent être utilisées pour créer des objets. Une classe abstraite peut inclure des méthodes avec une implémentation, mais ce n'est pas une exigence.

  4. Une interface est une construction de la construction du langage de programmation Java qui ne contient que des méthodes publiques abstraites et des champs constants statiques (statique final). En d'autres termes, ni les classes abstraites ni les interfaces ne peuvent être utilisées pour générer des objets.

BTW, dans Java 8 ou version ultérieure, les interfaces peuvent avoir non seulement des méthodes abstraites et des constantes, mais également des méthodes par défaut et statiques. En Java, une interface définit un comportement, tandis qu'une classe abstraite est utilisée pour créer une hiérarchie. Une interface peut être implémentée par plusieurs classes.

Exemple d'interface en code Java

interface Human {
	public void struggle();
	public void protect();
}

interface Vulcan {
	int angleOfPointyEars;
	public void turnOffEmotions(boolean isOn);
	public void telepathy();
}
Vous pouvez implémenter plus d'une interface
The Spock class implements Human and Vulcan {
public void struggle() {
System.out.println("I am struggling...");
}
	public void protect() {
System.out.println("You are under my protection!);
}
public void turnOffEmotions(boolean isOn){
If (isOn) {
System.out.println("I am turning off my emotions.");
isOn= !isOn;
}
}
	public void telepathy() {
System.out.println("Connecting to your brain...");
}

}
Pour les étudiants débutants, cela couvre tous les principaux concepts de la programmation orientée objet en Java. Outre les 4 principes principaux de la POO, Java a également l'association, l'agrégation et la composition. Vous pouvez les appeler "principes supplémentaires de la POO". Ils méritent leur propre article séparé.
Commentaires
  • Populaires
  • Nouveau
  • Anciennes
Tu dois être connecté(e) pour laisser un commentaire
Cette page ne comporte pas encore de commentaires