Java: introduction à la programmation orientée objet (POO)
Tags: java, programming, beginners, poo
Published: 2023-03-09 17:40:54

La programmation orientée objet (**POO**) est un **paradigme** de programmation populaire qui permet aux développeurs de créer des **applications** plus **modulaires** et **faciles à maintenir**. En Java, la POO est largement utilisée pour développer des applications de bureau, des applications Web et des applications mobiles. Dans cet article, nous allons passer en revue les principes de base de la programmation orientée objet en Java et les illustrer avec des exemples.

### Encapsulation

L'encapsulation est le premier principe de base de la programmation orientée objet. Elle consiste à regrouper des **propriétés** et des **méthodes** associées en une seule unité, appelée une **classe**. Les propriétés sont **cachées** à l'extérieur de la classe et ne peuvent être accédées que par des méthodes spéciales appelées accesseurs (**getters**) et mutateurs (**setters**). Cela permet de protéger les données et de contrôler leur modification.

Par exemple, voici une classe simple qui utilise l'encapsulation pour stocker et modifier une variable private (privée) "name":
```java
public class Person {
    private String name;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
}
```
La propriété "**name**" est déclarée comme privée, ce qui signifie qu'elle **ne peut être accédée directement en dehors de la classe** Person. Pour accéder à cette propriété, la classe définit deux méthodes publiques. 

La méthode "**getName()**" renvoie la valeur actuelle de la propriété "**name**", tandis que la méthode "**setName()**" prend un argument de type String et définit la valeur de la propriété "**name**".

En encapsulant la propriété "**name**" et en fournissant des **méthodes publiques** pour y accéder, la classe Person garantit que les **modifications de la propriété** "name" sont effectuées de manière contrôlée. Cela facilite également la **réutilisation du code** de la classe, car les autres parties du programme peuvent interagir avec la classe via ses méthodes publiques sans avoir à se soucier de la manière dont la propriété "name" est stockée ou modifiée.

### Héritage

L'héritage est un autre principe important de la POO. Il permet à une classe **d'hériter des propriétés et des méthodes d'une autre classe**. La classe héritante est appelée sous-classe ou classe dérivée, tandis que la classe dont elle hérite est appelée **super-classe** ou **classe de base**. La sous-classe peut **ajouter** des fonctionnalités supplémentaires ou **modifier** les fonctionnalités existantes héritées de la super-classe.

Par exemple, voici une **super-classe Animal** et une sous-classe **Dog** qui hérite de Animal et ajoute des méthodes et des propriétés spécifiques au chien:
```java
public class Animal {
    public void eat() {
        System.out.println("I am eating");
    }
}
```

```java
public class Dog extends Animal {
    public void bark() {
        System.out.println("Woof! Woof!");
    }
}
```
La classe Animal a une méthode publique "**eat()**" qui affiche un message indiquant qu'il est en train de manger. La classe **Dog** étend la classe Animal en **héritant de sa méthode** "**eat()**" et en **ajoutant** une méthode "**bark()**" qui affiche un message indiquant que le chien aboie.

En héritant de la classe **Animal**, la classe **Dog** peut réutiliser sa méthode "**eat()**" sans avoir à la redéfinir. Cela permet d'**éviter la duplication de code** et de **faciliter la maintenance** du code.

Dans cet exemple, la classe **Dog** est une forme de l'objet Animal et peut être utilisée partout où un objet Animal est attendu. Cependant, le chien a également un **comportement spécifique** à lui-même (le fait d'aboyer) qui peut être invoqué par la méthode **"bark()**".

### Polymorphisme

Le polymorphisme est un principe qui permet à une classe de se comporter de différentes manières. Cela signifie qu'un **objet** peut être utilisé comme une **instance** de **sa propre classe** ou comme une instance d'une de ses **sous-classes**.

Par exemple, considérez la classe **Animal** et ses sous-classes **Dog** et **Cat**. Supposons que nous ayons une méthode appelée "**makeSound()**" qui doit être appelée pour chaque animal. Dans ce cas, nous pouvons utiliser le polymorphisme pour appeler la méthode "**makeSound()**" pour n'importe quel type d'animal, sans savoir à l'avance s'il s'agit d'un chien ou d'un chat.
```java
public class Animal {
    public void makeSound() {
        System.out.println("The animal is making a sound");
    }
}
```

```java
public class Dog extends Animal {
    public void makeSound() {
        System.out.println("The dog is barking");
    }
}
```

```java
public class Cat extends Animal {
    public void makeSound() {
        System.out.println("The cat is meowing");
    }
}
```
La classe Animal a une **méthode publique** "**makeSound()**" qui affiche un message indiquant que l'animal fait un bruit. Les classes **Dog** et **Cat** étendent la classe **Animal** et **redéfinissent sa méthode** "**makeSound()**" en spécifiant le son spécifique que l'animal émet (aboiement pour le chien et miaulement pour le chat).

Le polymorphisme permet aux **objets** d'avoir des **comportements différents** en fonction de leur contexte d'utilisation. Cela facilite la **réutilisation du code** et permet de créer des **applications** Java **modulaires** et **évolutives**.

### Abstraction

L'abstraction est le quatrième principe de la programmation orientée objet. Il consiste à définir une **classe abstraite** qui contient des **méthodes abstraites** (**méthodes sans corps**) qui doivent être **implémentées** par ses **sous-classes**. L'abstraction permet de définir un ensemble commun de méthodes et de propriétés qui peuvent être utilisées par des classes distinctes, tout en garantissant que chaque sous-classe implémente ces méthodes de manière appropriée.

L'exemple ci-dessous montre comment la classe **Dog** peut utiliser l'abstraction pour cacher les détails de son implémentation derrière une interface simple:
```java
public abstract class Animal {
    public abstract void makeSound();
}
```

```java
public class Dog extends Animal {
    public void makeSound() {
        System.out.println("The dog is barking");
    }
}
```
Dans cet exemple, la classe **Animal** est déclarée comme étant **abstraite** avec une **méthode abstraite** "**makeSound()**". Cette méthode n'a pas d'implémentation dans la classe Animal, mais elle est déclarée pour que toutes les **classes qui étendent Animal soient obligées de la définir**.

La classe **Dog** étend la classe Animal et définit **sa propre implémentation** de la méthode "**makeSound()**". En utilisant l'abstraction, la classe Dog n'a pas besoin de fournir une implémentation pour toutes les autres méthodes définies dans la classe Animal. Au lieu de cela, elle peut se concentrer sur la **définition** de sa propre implémentation pour "**makeSound()**", qui est la seule **méthode abstraite** définie dans Animal.

La principale caractéristique d'une **classe abstraite** est qu'elle **ne peut pas être instanciée directement**, mais **doit être héritée** par une sous-classe qui implémente ses méthodes abstraites et/ou surcharge ses méthodes non abstraites. La présence de méthodes abstraites n'est qu'un des moyens de forcer une sous-classe à fournir une implémentation pour ces méthodes, mais ce n'est pas la seule façon. Par conséquent, une classe abstraite **peut ne pas contenir de méthode abstraite**.

L'abstraction permet aux développeurs de créer des classes génériques qui peuvent être utilisées de manière flexible dans différents contextes, sans avoir à se soucier des détails d'implémentation spécifiques à chaque sous-classe. Cela facilite la réutilisation du code et permet de créer des applications Java modulaires et évolutives.

### Composition

La composition est un autre principe important de la POO en Java. Elle consiste à **créer des objets complexes en combinant des objets plus simples**. Au lieu d'hériter des propriétés et des méthodes d'une autre classe, la composition utilise des instances de classe comme membres d'une autre classe pour créer un objet plus complexe.

L'exemple ci-dessous montre comment la composition peut être utilisée pour créer un objet "House" à partir d'objets plus simples tels que "Room" et "Door":
```java
public class Door {
    private String color;
    
    public Door(String color) {
        this.color = color;
    }
    
    public String getColor() {
        return color;
    }
}
```

```java
public class Room {
    private Door door;
    private String name;
    
    public Room(String name, Door door) {
        this.name = name;
        this.door = door;
    }
    
    public String getName() {
        return name;
    }
    
    public Door getDoor() {
        return door;
    }
}
```

```java
public class House {
    private Room[] rooms;
    
    public House(Room[] rooms) {
        this.rooms = rooms;
    }
    
    public Room[] getRooms() {
        return rooms;
    }
}
```
Dans cet exemple, nous avons trois classes: **Door**, **Room** et **House**. La classe Door représente une porte et a une propriété "color" qui définit sa couleur. La classe Room représente une pièce de la maison et a une propriété "name" qui définit son nom, ainsi qu'une propriété "door" qui est un objet Door qui représente la porte de la pièce.

La classe **House** représente une maison et a une propriété "**rooms**" qui est un **tableau d'objets Room** qui représente toutes les pièces de la maison. En utilisant la composition, nous pouvons **construire un objet House en combinant plusieurs objets Room, qui contiennent eux-mêmes des objets Door.
**
En conclusion, la **programmation orientée objet** en Java offre de nombreux avantages, notamment la **modularité**, la **réutilisabilité**, la **maintenabilité** et la **flexibilité**. En utilisant les principes de l'encapsulation, de l'héritage, du polymorphisme, de l'abstraction et de la composition, les développeurs peuvent créer des **applications** Java **robustes** et **évolutives**.