Concepts de programmation orientée objet en Java

1. Vue d'ensemble

Dans cet article, nous examinerons les concepts de programmation orientée objet (POO) en Java. Nous discuterons des classes, des objets, de l'abstraction, de l'encapsulation, de l'héritage et du polymorphisme .

2. Classes

Les classes sont le point de départ de tous les objets, et nous pouvons les considérer comme le modèle pour créer des objets. Une classe contient généralement des champs membres, des méthodes membres et une méthode de constructeur spéciale.

Nous allons utiliser le constructeur pour créer des objets de la classe:

public class Car { // member fields private String type; private String model; private String color; private int speed; // constructor public Car(String type, String model, String color) { this.type = type; this.model = model; this.color = color; } // member methods public int increaseSpeed(int increment) { this.speed = this.speed + increment; return this.speed; } // ... }

Notez qu'une classe peut avoir plusieurs constructeurs. Nous pouvons en savoir plus sur les classes dans notre article sur les classes.

3. Objets

Les objets sont créés à partir de classes et sont appelés instances de la classe. Nous créons des objets à partir de classes en utilisant leurs constructeurs:

Car veyron = new Car("Bugatti", "Veyron", "crimson"); Car corvette = new Car("Chevrolet", "Corvette", "black"); 

Ici, nous avons créé deux instances de la classe Car. En savoir plus à leur sujet dans notre article sur les objets.

4. Abstraction

L'abstraction cache les complexités de la mise en œuvre et expose des interfaces plus simples.

Si nous pensons à un ordinateur typique, on ne peut voir que l'interface externe, qui est la plus essentielle pour interagir avec lui, tandis que les puces et circuits internes sont cachés à l'utilisateur.

En POO, l'abstraction signifie masquer les détails d'implémentation complexes d'un programme, exposant uniquement l'API requise pour utiliser l'implémentation. En Java, nous réalisons l'abstraction en utilisant des interfaces et des classes abstraites.

Nous pouvons en savoir plus sur l'abstraction dans nos articles sur les classes abstraites et l'interface.

5. Encapsulation

L'encapsulation masque l'état ou la représentation interne d'un objet au consommateur d'une API et fournit des méthodes accessibles au public liées à l'objet pour un accès en lecture-écriture. Cela permet de masquer des informations spécifiques et de contrôler l'accès à l'implémentation interne.

Par exemple, les champs membres d'une classe sont masqués pour les autres classes et sont accessibles à l'aide des méthodes membres. Une façon de procéder consiste à rendre tous les champs de données privés et accessibles uniquement à l'aide des méthodes des membres publics :

public class Car { // ... private int speed; public int getSpeed() { return color; } public void setSpeed(int speed) { this.speed = speed; } // ... }

Ici, la vitesse du champ est encapsulée à l'aide du modificateur d'accès privé et n'est accessible qu'à l'aide des méthodes publiques getSpeed ​​() et setSpeed ​​() . Nous pouvons en savoir plus sur les modificateurs d'accès dans notre article sur les modificateurs d'accès.

6. Héritage

L'héritage est le mécanisme qui permet à une classe d'acquérir toutes les propriétés d'une autre classe en héritant de la classe. Nous appelons la classe héritière une classe enfant et la classe héritée comme la superclasse ou la classe parent.

En Java, nous faisons cela en étendant la classe parente. Ainsi, la classe enfant obtient toutes les propriétés du parent:

public class Car extends Vehicle { //... }

Lorsque nous étendons une classe, nous formons une relation IS-A. La voiture IS-A Vehicle . Donc, il a toutes les caractéristiques d'un véhicule .

Nous pouvons nous poser la question: pourquoi avons-nous besoin d'un héritage ? Pour répondre à cela, considérons un constructeur automobile qui fabrique différents types de véhicules, tels que des voitures, des bus, des tramways et des camions.

Pour faciliter le travail, nous pouvons regrouper les caractéristiques et propriétés communes de tous les types de véhicules dans un module (une classe dans le cas de Java). Et nous pouvons laisser des types individuels hériter et réutiliser ces propriétés:

public class Vehicle { private int wheels; private String model; public void start() { // the process of starting the vehicle } public void stop() { // process to stop the vehicle } public void honk() { // produces a default honk } }

Le type de véhicule Voiture héritera désormais de la classe de véhicule parent :

public class Car extends Vehicle { private int numberOfGears; public void openDoors() { // process to open the doors } }

Java prend en charge l'héritage unique et l'héritage à plusieurs niveaux. Cela signifie qu'une classe ne peut pas s'étendre directement à partir de plusieurs classes, mais qu'elle peut utiliser une hiérarchie:

public class ArmoredCar extends Car { private boolean bulletProofWindows; public void remoteStartCar() { // this vehicle can be started by using a remote control } }

Ici, l' ArmouredCar étend la voiture et la voiture étend le véhicule . Ainsi, ArmouredCar hérite des propriétés de la voiture et du véhicule .

Alors que nous héritons de la classe parent, un développeur peut également remplacer une implémentation de méthode du parent. C'est ce qu'on appelle le remplacement de méthode.

Dans notre exemple ci-dessus de la classe Vehicle , il existe la méthode honk () . La classe Car qui étend la classe Vehicle peut remplacer cette méthode et implémenter de la manière qu'elle souhaite produire le klaxon:

public class Car extends Vehicle { //... @Override public void honk() { // produces car-specific honk } }

Notez que cela est également appelé un polymorphisme d'exécution, comme expliqué dans la section suivante. Nous pouvons en savoir plus sur l'héritage dans nos articles sur l'héritage et l'héritage Java et la composition.

7. Polymorphisme

Le polymorphisme est la capacité d'un langage POO à traiter les données différemment en fonction de leurs types d'entrées. En Java, il peut s'agir du même nom de méthode ayant différentes signatures de méthode et exécutant différentes fonctions:

public class TextFile extends GenericFile { //... public String read() { return this.getContent() .toString(); } public String read(int limit) { return this.getContent() .toString() .substring(0, limit); } public String read(int start, int stop) { return this.getContent() .toString() .substring(start, stop); } }

Dans cet exemple, nous pouvons voir que la méthode read () a trois formes différentes avec des fonctionnalités différentes. Ce type de polymorphisme est un polymorphisme statique ou à la compilation et est également appelé surcharge de méthode.

Il existe également un polymorphisme à l' exécution ou dynamique, où la classe enfant remplace la méthode du parent :

public class GenericFile { private String name; //... public String getFileInfo() { return "Generic File Impl"; } }

Une classe enfant peut étendre la classe GenericFile et remplacer la méthode getFileInfo () :

public class ImageFile extends GenericFile { private int height; private int width; //... getters and setters public String getFileInfo() { return "Image File Impl"; } }

En savoir plus sur le polymorphisme dans notre article sur le polymorphisme en Java.

8. Conclusion

Dans cet article, nous avons découvert les concepts fondamentaux de base de la POO avec Java.

Les exemples de code de cet article sont disponibles à l'adresse over sur Github.