Débuter avec oop

Présentation de la POO

Présentation

La programmation orientée objet (principalement appelée OOP) est un paradigme de programmation permettant de résoudre des problèmes.
La beauté d’un programme OO (orienté objet) est que nous considérons le programme comme un ensemble d’objets communiquant entre eux, plutôt que comme un script séquentiel suivant des ordres spécifiques.

Il existe de nombreux langages de programmation qui prennent en charge la POO, certains des plus populaires sont :

  • Java -C++
  • c#

Python est également connu pour prendre en charge la POO, mais il lui manque quelques propriétés.


Terminologie POO

Le terme le plus basique en POO est une classe.
Une classe est essentiellement un * objet *, qui a un état et qui fonctionne en fonction de son état.

Un autre terme important est une instance.
Considérez une classe comme un modèle utilisé pour créer des instances d’elle-même. La classe est un modèle et la ou les instances sont les objets concrets.

Une instance créée à partir de la classe A est généralement désignée par le ’type A’, exactement comme le type de 5 est int et le type de “abcd” est une chaîne.

Un exemple de création d’une instance nommée insance1 de type (classe) ClassA :

###Java

instance ClassA1 = new ClassA();

C++

instance de classe A1 ; ou

ClassA * instance1 = nouvelle ClassA (); # Sur le tas

###Python

instance1 = ClasseA()

Comme vous pouvez le voir dans l’exemple ci-dessus, dans tous les cas, le nom de la classe a été mentionné et après il y avait des parenthèses vides (sauf pour le C++ où si elles sont vides, les parenthèses peuvent être supprimées). Entre parenthèses, nous pouvons passer des arguments au constructeur de notre classe.

Un constructeur est une méthode d’une classe qui est appelée à chaque fois qu’une instance est créée. Il peut prendre des arguments ou non. Si le programmeur ne spécifie aucun constructeur pour une classe qu’il construit, un constructeur vide sera créé (un constructeur qui ne fait rien).
Dans la plupart des langages, le constructeur est défini comme une méthode sans définir son type de retour et avec le même nom que la classe (exemple dans quelques sections).

Un exemple de création d’une instance nommée b1 de type (classe) ClassB. Le constructeur de ClassB prend un argument de type int :

###Java

instance ClassA1 = nouvelle ClassA(5); ou

entier je = 5 ; instance ClassA1 = nouvelle ClassA(i);

C++

instance de classe A1(5) ; ###Python

instance1 = ClasseA(5) Comme vous pouvez le voir, le processus de création d’une instance est très similaire au processus d’appel d’une fonction.


Fonctions vs Méthodes

Les fonctions et les méthodes sont très similaires, mais dans la conception orientée objet (OOD), elles ont chacune leur propre signification.
Une méthode est une opération effectuée sur une instance d’une classe. La méthode elle-même utilise généralement l’état de l’instance pour fonctionner.
Pendant ce temps, une fonction appartient à une classe et non à une instance spécifique. Cela signifie qu’il n’utilise pas l’état de la classe ni aucune donnée stockée dans une instance.

A partir de maintenant, nous ne montrerons nos exemples qu’en Java puisque la POO est très claire dans ce langage, mais les mêmes principes fonctionnent dans n’importe quel autre langage POO.

En Java, une fonction a le mot static dans sa définition, comme ceci :

// File's name is ClassA
public static int add(int a, int b) {
    return a + b;
}

Cela signifie que vous pouvez l’appeler de n’importe où dans le script.

// From the same file
System.out.println(add(3, 5));

// From another file in the same package (or after imported)
System.out.println(ClassA.add(3, 5));

Lorsque nous appelons la fonction à partir d’un autre fichier, nous utilisons le nom de la classe (en Java, c’est aussi le nom du fichier) à laquelle elle appartient, cela donne l’intuition que la fonction appartient à la classe et non à aucune de ses instances.

En revanche, nous pouvons définir une méthode en ClassA comme ceci :

// File's name is ClassA
public int subtract(int a, int b){
    return a - b;
}

Après cette déclaration, nous pouvons appeler cette méthode comme suit :

ClassA a = new ClassA();
System.out.println(a.subtract(3, 5));

Ici, nous devions créer une instance de ClassA afin d’appeler sa méthode subtract. Notez que nous NE POUVONS PAS faire ce qui suit :

System.out.println(ClassA.subtract(3, 5));

Cette ligne produira une erreur de compilation indiquant que nous avons appelé cette méthode non statique sans instance.


Utiliser l’état d’une classe

Supposons que nous voulions à nouveau implémenter notre méthode subtract, mais cette fois nous voulons toujours soustraire le même nombre (pour chaque instance). Nous pouvons créer la classe suivante :

class ClassB {

    private int sub_amount;

    public ClassB(int sub_amount) {
        this.sub_amount = sub_amount;
    }

    public int subtract(int a) {
        return a - sub_amount;
    }

    public static void main(String[] args) {
        ClassB b = new ClassB(5);
        System.out.println(b.subtract(3)); // Ouput is -2
    }
}

Lorsque nous exécutons ce code, une nouvelle instance nommée b de la classe ClassB est créée et son constructeur est alimenté avec la valeur 5.
Le constructeur prend maintenant le sub_amount donné et le stocke comme son propre champ privé, également appelé sub_amount (cette convention est très connue en Java, pour nommer les arguments de la même manière que les champs).
Après cela, nous affichons sur la console le résultat de l’appel de la méthode subtract sur b avec la valeur 3.

Notez que dans l’implémentation de subtract nous n’utilisons pas this. comme dans le constructeur.
En Java, this ne doit être écrit que lorsqu’il existe une autre variable portant le même nom définie dans cette portée. La même chose fonctionne avec le self de Python.
Ainsi, lorsque nous utilisons sub_amount dans subtract, nous référençons le champ privé qui est différent pour chaque classe.

Un autre exemple à souligner.
Modifions simplement la fonction main dans le code ci-dessus comme suit :

ClassB b1 = new ClassB(1);
ClassB b2 = new ClassB(2);

System.out.println(b1.subtract(10)); // Output is 9
System.out.println(b2.subtract(10)); // Output is 8

Comme nous pouvons le voir, b1 et b2 sont indépendants et ont chacun leur propre état.


Interfaces et Héritage

Une interface est un contrat, elle définit quelles méthodes une classe aura et donc ses capacités. Une interface n’a pas d’implémentation, elle définit seulement ce qui doit être fait.
Un exemple en Java serait :

interface Printalbe {
    public void print();
}

L’interface Printalbe définit une méthode appelée print mais elle ne donne pas son implémentation (assez bizarre pour Java). Chaque classe qui se déclare comme “implémentant” cette interface doit fournir une implémentation à la méthode draw. Par exemple:

class Person implements Printalbe {

    private String name;

    public Person(String name) {
        this.name = name;
    }

    public void print() {
        System.out.println(name);
    }
}

Si Person se déclarait comme implémentant Drawable mais ne fournissait pas d’implémentation à print, il y aurait une erreur de compilation et le programme ne compilerait pas.

L’héritage est un terme qui pointe vers une classe étendant une autre classe. Par exemple, disons que nous avons maintenant une personne qui a un âge. Une façon d’implémenter une telle personne serait de copier la classe Person et d’écrire une nouvelle classe appelée AgedPerson qui a les mêmes champs et méthodes mais qui a une autre propriété -age.
Ce serait affreux puisque nous dupliquons notre code ** entier ** juste pour ajouter une fonctionnalité simple à notre classe.
Nous pouvons utiliser l’héritage pour hériter de Person et ainsi obtenir toutes ses fonctionnalités, puis les améliorer avec notre nouvelle fonctionnalité, comme ceci :

class AgedPerson extends Person {

    private int age;

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

    public void print() {
        System.out.println("Name: " + name + ", age:" + age);
    }
}

Il y a quelques nouveautés :

  • Nous avons utilisé le mot enregistré extends pour indiquer que nous héritons de Person (ainsi que son implémentation dans Printable, nous n’avons donc pas besoin de déclarer à nouveau implementing Printable).
  • Nous avons utilisé le mot de sauvegarde super pour appeler le constructeur de Person.
  • Nous avons remplacé la méthode print de Person par une nouvelle.

Cela devient assez technique Java, donc je n’irai pas plus loin dans ce sujet. Mais je mentionnerai qu’il y a beaucoup de cas extrêmes qui doivent être appris sur l’héritage et les interfaces avant de commencer à les utiliser. Par exemple, quelles méthodes et fonctions sont héritées ? Qu’advient-il des champs privés/publics/protégés lors de l’héritage d’une classe ? etc.

Classe abstraite

Une classe abstraite est un terme assez avancé en POO qui décrit une combinaison d’interfaces et d’héritage. Il vous permet d’écrire une classe qui contient à la fois des méthodes/fonctions implémentées et non implémentées. En Java, cela se fait en utilisant le mot clé abstract et je ne l’expliquerai pas plus qu’un exemple rapide :

abstract class AbstractIntStack {

    abstract public void push(int element);

    abstract public void pop();

    abstract public int top();

    final public void replaceTop(int element) {
        pop();
        push(element);
    }
}

Remarque : le mot clé final indique que vous ne pouvez pas remplacer cette méthode lorsque vous héritez de cette classe. Si une classe est déclarée finale, aucune classe ne peut en hériter.

Introduction

OOP - La programmation orientée objet est un paradigme de programmation largement utilisé de nos jours. En POO, nous modélisons des problèmes du monde réel à l’aide d’objets et de leurs comportements, afin de les résoudre par programmation.

Il existe quatre principaux concepts OOP

  1. Héritage
  2. Polymorphisme
  3. Abstraction
  4. Encapsulation

Ces quatre concepts sont utilisés ensemble pour développer des programmes en POO.

Il existe différents langages qui supportent la programmation orientée objet. Les langues les plus populaires sont *C++ *Java *C#

  • Python (Python n’est pas entièrement orienté objet, mais possède la plupart des fonctionnalités POO)