L'héritage est un concept de programmation orientée objet qui permet de définir un type de données à partir d'un autre type de données qu'on va compléter.
Je vous propose donc de commencer par coder une classe de base. Nous appellerons cette classe Person
: elle permettra de représenter la notion
de personne qui agrégera trois attributs (un prénom, un nom de famille et un email).
Vous noterez que j'y ai rajouté des propriétés permettant de valider les changements d'état. En cas d'incohérence, une exception de type
PersonException
. En fait, il y a déjà un lien d'héritage à ce niveau. Effectivement, cette classe dérive de BaseException
(la classe de base de toutes les classes exceptions). Cette classe est fournie par l'environnement Python.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
#!/usr/bin/python3 class PersonException( BaseException ): # Un lien d'héritage !!! def __init__(self, message): super().__init__(message) class Person( object ): def __init__(self, firstName="john", lastName="doe", email=None): self.firstName = firstName self.lastName = lastName self.email = email @property def firstName(self): return self.__firstName @firstName.setter def firstName(self, newFirstName): """A non-empty and non-null character string in lowercase.""" if newFirstName is None: raise PersonException("firstName cannot be None") if not isinstance( newFirstName, str): raise PersonException("firstName must be a string") newFirstName = newFirstName.strip() if newFirstName == "": raise PersonException("firstName cannot be empty") self.__firstName = newFirstName.lower() @property def lastName(self): return self.__lastName @lastName.setter def lastName(self, newLastName): """A non-empty and non-null character string in uppercase.""" if newLastName is None: raise PersonException("lastName cannot be None") if not isinstance( newLastName, str): raise PersonException("lastName must be a string") newLastName = newLastName.strip() if newLastName == "": raise PersonException("lastName cannot be empty") self.__lastName = newLastName.upper() @property def email(self): return self.__email @email.setter def email(self, newEmail): """A non-empty character string or None value.""" if not newEmail is None: if not isinstance( newEmail, str): raise PersonException("lastName must be a string") newEmail = newEmail.strip() if newEmail == "": raise PersonException("lastName cannot be empty") self.__email = newEmail def __str__(self): mail = "-" if self.email is None else self.email return "%s %s - %s" % (self.firstName, self.lastName, mail) |
Maintenance nous pouvons dériver une classe Employee
de la classe Person
.
Notez, dans le constructeur et dans la méthode __str__
, la présence de super()
qui permet de rappeler
les méthodes de même noms, mais qui sont définies dans la classe parente (la super-classe).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#!/usr/bin/python3 from Person import Person, PersonException class Employee( Person ): def __init__(self, firstName="john", lastName="doe", email=None, salary = 0): super().__init__(firstName, lastName, email) self.salary = salary @property def salary(self): return self.__salary @salary.setter def salary(self, newSalary): if not isinstance(newSalary, float) and not isinstance(newSalary, int): raise PersonException("salary must be a numeric value") if newSalary < 0: raise PersonException("a salary must be positive or zero") self.__salary = newSalary def __str__(self): return "%s == %.2f euros" % (super().__str__(), self.salary) |
Afin de bien tester notre programme, je vous propose de mettre en place une petite batterie de test unittest.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
import unittest from Person import PersonException from Employee import Employee class TestCase(unittest.TestCase): def testGoodProperties(self): zorro = Employee( "Zorro", "De La Vega ", None, 2000 ) self.assertEqual("zorro", zorro.firstName) self.assertEqual("DE LA VEGA", zorro.lastName) self.assertIsNone(zorro.email) self.assertEqual(2000, zorro.salary) def testBadFirstName(self): with self.assertRaises(PersonException): Employee("", "Doe", None, 0) def testBadLastName(self): with self.assertRaises(PersonException): Employee("John", None, None, 0) def testBadEmail(self): with self.assertRaises(PersonException): Employee("toto", "Doe", 10, 0) def testBadSalary(self): with self.assertRaises(PersonException): Employee("John", "Doe", None, -1000) if __name__ == "__main__": #import sys;sys.argv = ['', 'Test.testName'] unittest.main() |
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :