POO, documentation et tests - TP6

Relations entre classes
Author

Ludovic Deneuville

Introduction

Créer l’arborscence

Vous pouvez créer chaque dossier et fichier à la main, ou utiliser dans un terminal Git Bash les commandes ci-dessous (mkdir : make directory):

# Sur la VM ensai
mkdir -p /p/Cours1A/IPOO/TP6/Exercice_{1..3}/

# Sur un Datalab Onyxia
mkdir -p /home/onyxia/work/IPOO/TP6/Exercice_{1..3}/

Moodle

1 Cours

1.1 Héritage et classes abstraites

Une classe abstraite ne peut pas être instanciée, c’est à dire qu’on ne peut pas créer d’objets de cette classe.

L’intérêt est de fournir un socle commun à des classes filles.

Exemple :

  • les voitures et les vélos ont des attributs et méthodes communes
  • tout ce qui leur est commun est codé dans la classe Vehicule dont ils héritent
  • ce qui les différencie est codé dans leurs propres classes
  • la partie commune du constructeur est codé dans la classe mère
  • la méthode accelerer() est déclarée abstraite dans la classe mère
    • ce qui veut dire que toutes les classes filles devront redéfinir cette méthode
vehicule.py
from abc import ABC, abstractmethod

class Vehicule(ABC):
    def __init__(self, nb_roues):
        self.nb_roues = nb_roues
        self.vitesse = 0

    @abstractmethod
    def accelerer(self):
        pass
voiture.py
class Voiture(Vehicule):
    def __init__(self, marque, nb_roues):
        super().__init__(nb_roues=4)
        self.marque = marque

    def accelerer(self):
        self.vitesse += 20
velo.py
class Velo(Vehicule):
    def __init__(self, porte_bagages, nb_roues):
        super().__init__(nb_roues=2)
        self.porte_bagages = porte_bagages

    def accelerer(self):
        self.vitesse += 5

2 Exercices

2.1 Exercice 1

      • dans votre Explorer à gauche apparait l’arborescence des dossiers et fichiers de Exercice_1
Caution
  • attributs publics : arguments des constructeurs des classes
  • attributs protégés : initialisés dans les constructeurs
    • avec ses attributs et méthodes
    • Que peut-on dire de la classe Emploi ?
Tip

Pour vérifier si votre code est correct, vous pouvez utiliser ce code même si ce n’est pas une bonne pratique.

Le mieux est de faire des TU !

main.py
from emploi import Emploi
from entreprise import Entreprise
from personne import Personne

personne = Personne(
    'Dupont', 'Marie', 23, "Diplôme d'ingénieur de l'ENSAI", ""
)

entreprise = Entreprise('Entreprise préférée', 'Lyon', 23_000_000)

emploi = Emploi(personne, entreprise, 'CDI', '2022/09/01', None)

print(f"Expérience professionnelle :\n{personne.experience_professionnelle}")
print("Est-ce que la personne a déjà démissionné ?", personne._demission)
print("Combien d'employés ont démissionné de l'entreprise ?",
      entreprise._nombre_demissions)
print()

emploi.rupture_contrat('2023/08/31', 'démission')

print("Est-ce que la personne a déjà démissionné ?", personne._demission)
print("Combien d'employés ont démissionné de l'entreprise ?",
      entreprise._nombre_demissions)
print(f"Expérience professionnelle :\n{personne.experience_professionnelle}")

2.2 Exercice 2

Pour Lancer les tests unitaires avec pytest.

Aide
    • pour lancer les TU sur Aeroport
      • positionnez-vous dans le bon dossier
      • lancez python -m pytest --tb=short test_aeroport.py
  • Dans les constructeurs, vérifiez tous les types

    def __init__(self, nom)
        if not isinstance(nom, str):
            raise TypeError("Le nom doit être une chaîne de caractères.")
        self.nom = nom
  • from aeroport import Aeroport

2.3 Exercice 3

  • une classe abstraite hérite de ABC
  • une méthode abstraite est précédée par le décorateur @abstractmethod
  • le mot clé super() permet de faire référence à la classe mère
from abc import ABC, abstractmethod

3 Templates

3.1 Classe

class MaClasse:
    """titre_ma_classe

    Description

    Attributes
    ----------
    attribut_1 : type_attribut_1 (str, int, float, list, bool, function...)
        desc_attribut_1
        
    attribut_2 : type_attribut_2
        desc_attribut_2
    """
    
    def __init__(self, parametre_1, parametre_2):
        """Constructeur de l'objet

        Parameters
        ----------
        parametre_1 : type_parametre_1
            desc_parametre_1
            
        parametre_2 : type_parametre_2
            desc_parametre_2
        """
        self.attribut_1 = parametre_1
        self.attribut_2 = parametre_2

    def ma_methode(self, param1):
        """desc_courte_ma_methode

        desc_longue_ma_methode_facultatif       

        Parameters
        ----------
        param1 : type
            desc_param_1
            
        Returns
        -------
        type
            desc_retour

        Examples
        --------
        >>> mon_obj = ma_classe("toto")
        >>> mon_obj.ma_methode("xxx")
        2
        """
        return 2

    def __str__(self):
        """Conversion de l'objet en chaîne de caractères
        
        Examples
        --------
        >>> mon_obj = ma_classe("toto")
        >>> print(mon_obj)
        Classe d'attribut_1 égal à toto
        """
        return f"Classe d'attribut_1 égal à {self.attribut_1}"

3.2 Fonction

Voici un modèle que vous pouvez utiliser pour documenter vos fonctions

def ma_fonction(param1, param2):
    """description_courte

    description_longue

    Parameters
    ----------
    param1 : type (str, int, float, list...)
        description_param1
    param2 : type
        description_param2

    Returns
    -------
    type_retour
        description_retour

    Examples
    --------
    >>> 1+1
    2
    >>> print("abc")
    abc
    >>> ma_fonction(xxx, yyy)
    valeur_esperee
    """
    return None


if __name__ == '__main__':
    a = ma_fonction(p1, p2)
    print(a)