Concepts Fondamentaux de la Programmation Orientée Objet¶

Objets & Héritage¶

Agenda¶

1. Plonger dans un "cas d'école"¶

2. Une "Non" Solution¶

3. Regarder une Solution¶

4. Syntaxe Spécifiqueaux Objets¶

5. Classes et instances¶

6. Héritage¶

7. Les Subtilités de l'Héritage¶

Le Cas d'École¶

ss

Tâche¶

Contexte¶

Dans un système d'identification de personnes pour une compagnie d'assurance.

Tâche¶

  • Ajouter la notion de cartes d'identités gouvernementales.

  • S'assurer que la carte est "valide".

  • S'assurer que la personne est majeure.

Cartes d'Identités Gouvernementales.¶

Considérons 3 cas:¶

C'est Quoi l'Information sur les Cartes¶

Une "Non" Solution¶

Nous Pourrions Utiliser Plein de Variables¶

function validatePerson(
     firstName,
     lastName,
     dateOfBirth,
     expiration,
     healthInsuranceNumber,
     driverLicenseNumber,
     passportNumber,
     dateOfDelivery 
) {
         // s'assurer que la carte d'identité soit valide

         // s'assurer que la personne soit agée de 18 ans ou plus

}

Ok.. Ça marche..¶

Ça arrive toujours, soyez indulgent!¶

Mais nous pouvons tout de même demander mieux¶

Ce que nous voulons¶

1. Encapsuler les composantes qui, sémantiquement, font partie d'un même ensemble¶

2. Placer la logique le plus près possible des composantes¶

3. Partager les parties communes¶

Regarder une Solution¶

Définition: instance¶

Une instance est constitué de données encapsulées ainsi que de fonctions sur ces données. On appelle ces fonctions des Méthodes.¶

Les instances apportent une solution à nos deux premiers points.¶

1. Encapsuler les composantes qui, sémantiquement, font partie d'un même ensemble¶
2. Placer la logique le plus près possible des composantes¶

L'héritage permet de partager un noyau (de données et/ou de méthodes) entre plusieurs objets. Mais ça... nous le verrons plus tard.¶

On a déjà utilisé un "instance" très féquemment dans le cours...¶

$$ 1 + 1 = 11 $$

Les strings!¶

Vous ne le savez pas, mais les strings sont faits de 3 choses..¶

Pour l'utilisateur, un objet string est 100% opaque!¶

const text =  "Il aurait pu sans doute se procurer une installation plus commode, mais il appartenait à la catégorie des gens qui aiment à se rendre les conditions de la vie difficiles, pour avoir le droit d'être sombres et taciturnes";

const passage = text.substring(72, 170);

Appel à une Méthode¶

text.substring(72, 170);
//  ^ le "point" indique que nous appelons une méthode de l'objet.

C'est Vraiment Cool!¶

"pu sans doute se procurer une installation".includes("procurer");

"bonjour".concat(" monde");

"  beaucoup d'espaces ".trim();

"woohoo".toUpperCase();

Dans notre cas...¶

Nous voudrions être capable de faire..

if( !idCard.isMajor() ){
    return 
}

Syntaxe Spécifique aux Objets¶

Créer un objet...¶

const drivingLicense = new  DrivingLicense("paul", 
                                           "levesque", 
                                           "1985-11-24");

Appeler une méthode¶

drivingLicense.isMajor();

Classes et Instances¶

s

Définition: Classe¶

Une classe est le "plan" pour construire une instance. La classe définit...¶

1. Les données de l'instance. Une donnée associée à un objet est appelée un "champ"¶

2. Les méthodes de l'instance¶

3. Quoi faire lorsqu'un instance est créé¶

Exemple¶

class CoreId {
    firstName;
    lastName;
    dateOfBirth

    constructor(firstName,
                lastName,
                dateOfBirth) {
        this.firstName = firstName;
        this.lastName = lastName
        this.dateOfBirth = dateOfBirth;
    }

    getName(){
        return this.firstName + " " + this.lastName;
    }
}

const coreId =  new CoreId("didier", "amyot", "1985-11-17");
console.log(coreId.getName()); // didier amyot

Notation¶

const coreId =  new CoreId("didier", "amyot", "1985-11-17");
Ici, nous dirons que coreId est une instance de CoreId.¶

Recevoir un objet en argument¶

function sayHello(coreId){ // nom de la class de l'objet a recevoir
    console.log(coreId.getName());
}

Héritage¶

ss

Héritage: Idée générale¶

Nous voulons créer une classe B qui possède toutes les caractérisques d'une classe A avec des additions.¶

Exemple.. Classe A¶

class CoreId {
    firstName;
    lastName;
    dateOfBirth

    constructor(firstName,
                lastName,
                dateOfBirth) {
        this.firstName = firstName;
        this.lastName = lastName
        this.dateOfBirth = dateOfBirth;
    }

    getName(){
        return this.firstName + " " + this.lastName;
    }
}

Exemple.. Classe B¶

class Passport {
    constructor(firstName,
                lastName,
                dateOfBirth,
                passportNumber) {
        this.firstName = firstName;
        this.lastName = lastName
        this.dateOfBirth = dateOfBirth;
        this.passportNumber = passportNumber;
    }

    getName(): string{
        return this.firstName + " " + this.lastName;
    }
}

Vite vite comment ça...¶

On copie beaucoup de code¶
Il faut réécrire les fonctions qui prennent des CoreId¶
// typescript
function sayHello(tis){ // ne fonctionnera pas avec Passport
    console.log(tis.getName());
}
// typescript
function sayHello(tis: Passport){ // ne fonctionnera pas avec CoreId
    console.log(tis.getName());
}

La Solution: L'Héritage¶

class Passport extends CoreId {
    passportNumber: string;

    constructor(firstName: string,
                lastName: string,
                dateOfBirth: string,
                passportNumber: string) {
        super(firstName, lastName, dateOfBirth);
        this.passportNumber = passportNumber;
    }
}

Pourquoi c'est une solution?¶

Moins de code¶
  • Tous les champs et les méthodes de CoreId sont hérités par Passport

Toutes les fonctions qui prennent des CoreId prennent aussi des Passport¶

  • C'est ce que nous appelons le "Principe de substitution de Liskov"

Les subtilités de l'héritage¶

Big Bold Statement..¶

...

...

L'héritage, c'est un peu ce qui définie la programmation orientée objet.

-- didier

L'héritage créer un arbre de classes¶

L'héritage créer un arbre de classes¶

L'héritage créer un arbre de classes¶

La faille dans l'Héritage¶

ss

Contexte¶

Nous voullons créer une fonction isValid.

Problème!¶

// dans CoreId
isValid() {
    return true;
}
// dans Passport
isValid() {
    return this.verifyPassportNumber() && this.verifyExpirationDate();
}

Ceci brise l'idée générale d'héritage..¶

Mais on peut le faire: "Method overriding"¶

class CoreId {
    isValid(): boolean{
        return true;
    }
}

class Passport extends CoreId {
    isValid(): boolean{
        return this.verifyPassportNumber() && this.verifyExpirationDate();
    }
}

Il ne faut pas abuser de cela¶

En programmation orientée objet, le principe ouvert/fermé (open/closed principle) affirme qu'une classe doit être à la fois ouverte (à l'extension) et fermée (à la modification).

-- Bertrand Meyer

Fin¶

fin

Sources & Liens¶

  • Code source de la présentation: https://gitlab.com/didiercrunch/programming-101