Mission 9 : Héritage

Mission 9 : Héritage

Introduction

Le traitement de données commerciales et financières est un des champs majeurs d'application de l'informatique. De nos jours, la moindre PME utilise l'informatique pour gérer sa comptabilité, ses commandes et sa facturation, et l'infrastructure informatique est devenue un élément critique de toute grande entreprise, dont la supervision représente un poste clé au sein de l'exécutif, celui de Chief Information Officer ou CIO.

Invoice Manager, un logiciel de facturation pour PME. (© Hillstone Software)

PCLine s.p.r.l., une société de vente de matériel et de service informatique locale de Louvain-la-Neuve, fait appel à vos services pour développer ses applications informatisées de facturation. Les gérants de PCLine disposent déjà d'un programme pour imprimer leurs factures et calculer la TVA et les totaux. Ils désirent développer également la livraison des articles et de pièces, en intégrant l'impression des bordereaux de livraison dans leur logiciel de facturation existant, sans devoir écrire complètement leur logiciel existant. Heureusement, leur logiciel étant écrit en Python dans un style orienté objets, leur consultant de l'UCL leur a confirmé qu'il était possible de l'étendre sans le modifier au moyen des mécanismes d'héritage de Python. Ils ont donc confié aux étudiants de 1er Bac la tâche d'ébaucher la représentation des pièces en catalogue, leur intégration dans la facturation, ainsi que l'impression des bordereaux de livraison en plus de l'impression des factures.

Objectifs

A l'issue de cette mission, chacun d'entre vous :

  • pourra expliquer en ses propre mots et illustrer par l'exemple les principes de l'héritage en Python:

    • l'héritage d'une classe, la redéfinition de méthodes;
    • les notions d'héritage, de polymorphisme, et d'hiérarchie de classes;
    • l'utilisation de self et super();
  • sera capable d'utiliser l'héritage pour étendre un programme Python;

  • pourra rendre privé les variables d'instance d'une classe et écrire des méthodes pour y accéder;

  • aura appris les notions de variables et méthodes de classe et leur utilité;

  • pourra utiliser les méthodes magiques comme :

    • __init__ pour initialiser les objets d'une classe;
    • __str__ pour retourner une représentation textuelle d'un instance d'une classe;
    • __eq__ pour définir l'égalité entres objets d'une classe;

Préparation, étude et apprentissage

La matière relative à cette mission est décrite dans les sections suivantes de la partie Objects du syllabus en ligne:

ainsi que les annexes:

Questionnaire de démarrage

Questions à choix multiple

Les questions à choix multiples de cette mission sont accessibles en ligne depuis https://inginious.info.ucl.ac.be/course/LSINF1101-PYTHON/Session10_QCM

Please log in to see this exercise

Questions ouvertes

Question 1 : Héritage

L'héritage est un principe de base de la programmation orientée objet. Considérons les classes A, B, C et D ci-dessous :

class A :

  def m1(self) :
      print("A 1")

  def m2(self) :
      print("A 2")

  def m3(self) :
      self.m1()   # appel à la méthode m1 sur la même instance

  def nom(self) :
      return "A"

class B(A) :

  def m2(self):
      print("B 2")

class C(A):

    def m1(self) :
        print("C 1")

    def nom(self):
        return "C"

class D(C) :

    def m2(self) :
        print("D 2")

Considérant ces quatre classes, on vous demande de :

  • Expliquez ce que représente le mot self dans la définition de ces différentes méthodes.
 
 
 
 

  • Dessiner un diagramme reprenant ces quatre classes.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

  • Expliquer ce qui sera affiché lors de l'exécution des instructions Python ci-dessous :
a = A()
print(a.nom())
a.m1()
a.m2()
a.m3()
b = B()
print(b.nom())
b.m1()
b.m2()
b.m3()
c = C()
print(c.nom())
c.m1()
c.m2()
c.m3()
d = D()
print(d.nom())
d.m1()
d.m2()
d.m3()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Question 2 : super()

  • Expliquez le rôle de la fonction spécial super() dans le langage Python. Donnez un exemple.
 
 
 
 
 

  • Considérons les classes E et F ci-dessous :
class E :

    def m(self) :
        print("E 1")

    def n(self) :
        print("E 2")

    def p(self) :
        self.n()   # appel à la méthode m1 sur la même instance

class F(E) :

   def q(self) :
       print("F 1")

   def n(self) :
       super().n() # appeler la méthode définie sur la classe mère
       print("F 2")

   def r(self) :
        self.m() # appel à la méthode m1 sur la même instance

Expliquer ce qui sera affiché lors de l'exécution des instructions Python suivantes :

f = F()
f.q()
f.m()
f.r()
f.n()
f.p()
 
 
 
 
 
 
 

Question 3 : Rectangle

Considérons la classe Figure reprise ci-dessous :

class Figure:

    def __init__(self,x,y,visible=False) :
        """
        @pre x, y sont des entiers représentant des positions sur l'écran
        @post Une figure a été créée avec centre de gravité aux coordonnées x,y.
              Cette figure n'est initialement pas visible.
        """
        self.x = x
        self.y = y
        self.__visible = visible

    def estVisible(self) :
        """
        @pre -
        @post a retourné la visibilité de cette figure
        """
        return self.__visible

    def surface(self) :
        """
        @pre -
        @post la surface (un float) de la figure a été calculé et retournée
        """
        pass            # code non fourni

Cette classe Figure est la classe mère d'un ensemble de classes permettant de représenter des figures géométriques. Chaque figure géométrique est placée à une position (x,y) (centre de gravité) sur l'écran et la classe contient des variables d'instance et des méthodes permettant de manipuler cette figure géométrique (notamment des méthodes permettant d'afficher la figure à l'écran, mais ces méthodes ne sont pas reprises dans les extraits présentés dans cet exercice). Parmi ces figures géométriques, on trouve notamment la classe Rectangle qui hérite de la classe Figure et dont un fragment est repris ci-dessous :

class Rectangle(Figure):

    def __init__(self,lo,la,x,y) :
        """
        @pre lo (longeur) et la (largeur) sont des entiers positifs
             x, y sont des entiers représentant des positions sur l'écran
        @post un rectangle dont le centre de gravite est en x,y
              et ayant comme longueur lo et comme largeur la a été créé
        """
        super().__init__(x,y)
        self.longeur = lo
        self.largeur = la

    def __str__(self) :
        return str((self.longeur,self.largeur,self.x,self.y,self.estVisible()))

>>> r = Rectangle(10,20,0,0)
>>> print(r)
(10, 20, 0, 0, False)

Maintenant expliquez :

  • Quelles sont les variables d'instance qu'une instance de la classe Rectangle peut utiliser ?
  • Que se passe-t il lorsqu'une instance r de la classe Rectangle est créé?
  • Que fait l'appel à super() dans la méthode __init__ de la classe Rectangle ?
  • Que se passe-t il si on met cet appel à super() comme dernière instruction dans la méthode __init__ de la classe Rectangle ?
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Dans la classe Rectangle, faut-il redéfinir les méthodes suivantes (si oui, écrivez le code de la nouvelle méthode - si non, expliquez pourquoi ):

  • surface()
 
 
 
 
 
 
 
 

  • estVisible()
 
 
 
 

Question 4 : Variables privés

Pour éviter de rendre accessible les variables x, y et visible à l'extérieur d'une Figure, quelqu'un modifie le code de la classe Figure. Concrètement, pour rendre ces variables privés, on ajoute un __ à leur nom, comme suit :

class Figure:

    def __init__(self,x,y,visible=False) :
        """
        @pre x, y sont des entiers représentant des positions sur l'écran
        @post Une figure a été créée avec centre de gravité aux coordonnées x,y.
              Cette figure n'est initialement pas visible
        """
        self.__x = x
        self.__y = y
        self.__visible = visible


    def estVisible(self) :
        """
        @pre -
        @post a retourné la visibilité de cette figure
        """
        return self.__visible

    def surface(self):
        """
        @pre -
        @post la surface (un float) de la figure a été calculé et retournée
        """
        pass            # code non fourni

Malheureusement, le code de la classe Rectangle, qui hérite de la classe Figure ne marche plus maintenant. Quel est le problème?

 
 
 
 

Comment peut-on corriger ce problème? Corrigez le code afin que les instructions suivantes produisent le résultat voulu.

>>> r = Rectangle(10,20,0,0)
>>> print(r)
(10,20,0,0,False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Question 5 : Carre

Comment feriez-vous maintenant pour définir une classe Carre qui étend la classe Rectangle et permet de représenter un carré ?

  • Ecrivez la méthode d'initialisation de la classe Carre (un carré se construit en indiquant les coordonnées de son centre de gravité et la longueur de son côté)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

  • Quelles sont les méthodes que vous devez redéfinir dans la classe "Carre" ?
 
 
 
 

  • Soient deux classes Circle et Ellipse. Quelles relations peut-on envisager entre ces deux classes ?
 
 
 
 

  • Ecrivez une méthode perimetre() de la classe Rectangle qui retourne le périmètre du rectangle.
 
 
 
 

  • Que faudrait-il faire pour avoir une méthode perimetre de la classe Carre?
 
 
 
 

Question 6 : Similitude

Définissez une méthode __eq__ pour la classe Figure, telle que deux figures sont égales si leur surface est égale.

 
 
 
 

Que se passe-t il si on veut comparer deux rectangles ayant la même surface? Par exemple:

>>> r1 = Rectangle(10,40,0,0)
>>> r2 = Rectangle(2,200,0,0)
>>> r1 == r2
 
 
 
 

Que se passe-t il si on veut comparer un rectangle avec un carré ayant la même surface? Par exemple:

>>> r = Rectangle(10,40,0,0)
>>> c = Carre(20,0,0)
>>> print(r == c)
 
 
 
 

Question 7 : Ticket

Please log in to see this exercise


Page précédente Page suivante
<string>