Méthodologie de la programmation - séance 4

publicité
Méthodologie de la programmation
Pablo Rauzy
pablo·rauzy @ univ-paris8·fr
pablo.rauzy.name/teaching/mdlp
UFR MITSIC / L1 informatique
Séance 4
La programmation objet avec Python
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
1 / 23
La programmation objet avec Python
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
2 / 23
Cette séance
I Objectifs :
• Donner un aperçu du paradigme de la programmation orientée objet.
• Comprendre son intérêt, ses points forts.
I On va pour cela réutiliser le langage Python.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
3 / 23
Programmation orientée objet
I Paradigme de programmation inventé par Ole-Johan Dahl et Kristen Nygaard au
début des années 1960 et poursuivi par les travaux d’Alan Kay dans les années 1970.
I L’idée est de définir des briques logicielles appelées objets.
I Un objet représente un concept, une idée, ou toute entité du monde physique.
I Il possède une structure interne (implémentation) et un comportement (interface).
I Le but de cette méthode est double :
• permettre une meilleure modélisation des problèmes, et donc une meilleure
programmation,
• obtenir des briques logiciel facilement réutilisable en dissociant l’implémentation de
l’interface. On appelle cette pratique l’encapsulation.
I Explosion de la POO dans les années 80 et 90.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
4 / 23
Programmation orientée objet
Différentes façons d’être orienté objet
I On peut programmer orienté objet dans n’importe quel langage.
I Certains langages offre un support natif de la POO :
Smalltalk, Objective-C, Java, C++, Go, PHP, Python, Self, JavaScript, . . .
I Mais pas tous de la même façon :
• avec des classes qu’on instancie (C++, Java, Python) ;
• avec des prototypes qu’on clone (Self, JavaScript) ;
• d’autres choses moins clairement nommées (Go).
I Avec différentes façons de typer :
• typage fort ou faible (Python vs. JavaScript) ;
• typage statique ou dynamique (OCaml vs. Racket).
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
5 / 23
Programmation orientée objet
Le cas de Python
I Python supporte la programmation orientée objet à base de classes.
I Il est dynamiquement typé.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
6 / 23
Classes
I Une classe est une structure qui peut aussi avoir des fonctions comme membre.
On parle alors de méthodes.
I On appelle les variables membres des attributs.
I Comme pour les structures, on dit qu’on crée une instance d’une classe lors de la
création d’un objet qui a cette classe pour type.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
7 / 23
Méthodes
I Lorsqu’une méthode est appelée sur une instance, elle reçoit cette instance en
argument.
• Dans certains langages, le passage de cet argument est entièrement implicite, et son nom
est alors le plus souvent le mot-clef this.
• En Python, c’est le premier argument de la méthode et on le nomme généralement self,
par convention.
I Il existe une méthode spéciale qu’on appelle le constructeur de la classe et qui est
chargée de l’initialisation des attributs.
• Parfois c’est la méthode qui a le même nom que la classe.
• En Python, c’est la méthode qui s’appelle __init__.
• C’est la méthode qui est appelée quand on instancie la classe.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
8 / 23
Exemple
I Reprenons notre exemple de la structure qui représente une personne :
1
2
3
4
class Person:
def __init__ (self, age, name):
self.name = name
self.age = age
5
6
7
8
def presentation (self):
print("Bonjour je m'appelle " + self.name
+ " et j'ai " + str(self.age) + " ans.")
9
10
11
jd = Person(22, "John Doe") # instanciation
jd.presentation()
12
13
14
jd.name = "Jane Doe"
print("Mon nouveau nom est " + jd.name + ".")
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
9 / 23
Encapsulation
I Le code qu’on vient de voir n’est pas bon !
I Une des forces de la programmation orientée objet est l’encapsulation.
I Il s’agit de cacher les détails de l’implémentation d’une classe à ses utilisateurs, et
de leur offrir une interface stable.
I De cette façon,
• l’implémentation peut changer sans que l’utilisateur ne s’en soucie,
• et les objets sont seuls responsables du maintien de leur cohérence interne.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
10 / 23
Encapsulation
Exemple : changement d’implémentation, cassage d’interface
I Si on décide a un moment de changer l’implémentation, le code utilisateur de la
classe peut casser :
1
2
3
4
5
6
7
class Person:
def __init__ (self, age, firstname, lastname = None):
if lastname is None:
firstname, lastname = firstname.split(" ")
self.firstname = firstname
self.lastname = lastname
self.age = age
8
9
10
11
def presentation (self):
print("Bonjour je m'appelle " + self.firstname + " "
+ self.lastname + " et j'ai " + str(self.age) + " ans.")
12
13
14
jd = Person(22, "John Doe")
jd.presentation()
15
16
17
jd.name = "Jane Doe"
print("Mon nouveau nom est " + jd.name + ".")
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
11 / 23
Encapsulation
Politiques d’accès
I Pour mettre en œuvre l’encapsultation, la POO propose de restreindre l’accès aux
membres d’une classe.
existe trois niveaux de restriction :
I Il
•
•
•
publique : accès libre par tous,
privée : accès réservé aux méthodes de la classe propriétaire,
protégée : niveau intermédiaire que l’on verra plus tard en étudiant les notions d’héritage
et de hiérarchie de classes.
I En Python ces notions ne sont pas directement supportées, mais il existe une
convention :
• quand son nom commence par __, un membre est privé,
• quand son nom commence par _, un membre est protégé,
• sinon, un membre est public.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
12 / 23
Encapsulation
accesseurs
I Pour cette raison l’interface d’une classe offre généralement des accesseurs.
I Un accesseur est une méthode qui permet de lire ou écrire dans un attribut.
I Cela permet à la classe de contrôler la bonne formation de ses objets, tout en offrant
une interface stable aux utilisateurs.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
13 / 23
Encapsulation / accesseurs
Exemple
I Première version de la classe Person avec accesseurs :
1
2
3
4
class Person:
def __init__ (self, age, name):
self._name = name
self._age = age
5
6
7
def set_name (self, name):
self._name = name
8
9
10
def get_name (self):
return self._name
11
12
# ...
13
14
15
jd = Person(22, "John Doe")
jd.presentation()
16
17
18
jd.set_name("Jane Doe")
print("Mon nouveau nom est " + jd.get_name() + ".")
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
14 / 23
Encapsulation / accesseurs
Exemple
I Seconde version de la classe Person avec accesseurs :
1
2
3
4
5
6
7
class Person:
def __init__ (self, age, firstname, lastname = None):
if lastname is None:
firstname, lastname = firstname.split(" ")
self._firstname = firstname
self._lastname = lastname
self._age = age
8
9
10
11
12
def set_name (self, name):
firstname, lastname = firstname.split(" ")
self._firstname = firstname
self._lastname = lastname
13
14
15
def get_name (self):
return self._firstname + " " + self._lastname
16
17
# ...
18
19
20
jd = Person(22, "John Doe")
jd.presentation()
21
22
23
jd.set_name("Jane Doe")
print("Mon nouveau nom est " + jd.get_name() + ".")
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
15 / 23
Héritage
I Une classe qui hérite d’une autre récupère ses membres et peut en définir de
nouveaux ou redéfinir ceux qui sont hérités.
I En Python, une classe peut hériter de plusieurs classes.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
16 / 23
Héritage
Vocabulaire
I La classe héritante est appelée classe dérivée (ou sous classe).
I Les classes héritées sont appelées classes de base directes (ou super classe).
I Une classe de base d’une classe dérivée est soit une classe de base directe, soit une
classe de base directe d’une classe de base.
I On parle d’héritage simple quand il n’y a qu’une seule classe de base directe.
I Sinon, on parle d’héritage multiple.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
17 / 23
Héritage
Exemple
I Un·e étudiant·e est une personne, il partage donc les même attributs :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Student:
def __init__ (self, age, firstname, lastname, year, department):
self._firstname = firstname
self._lastname = lastname
self._age = age
self._year = year
self._dept = department
def set_name (self, name): # ...
def get_name (self): # ...
def set_year (self, year):
self._year = year
def get_year (self):
return self._year
def presentation (self):
print("Bonjour je m'appelle " + self.get_name()
+ " et j'ai " + str(self._age) + " ans.")
print("Je suis en " + self._year + " au département "
+ self._dept + ".")
19
20
21
js = Student(22, "Jane", "Doe", "L3", "MITSIC")
js.set_name("Jane Smith")
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
18 / 23
Héritage
Exemple
I C’est donc une bonne idée d’utiliser l’héritage :
1
2
3
4
5
class Student (Person):
def __init__ (self, age, firstname, lastname, year, department):
Person.__init__(self, age, firstname, lastname)
self._year = year
self._dept = departement
6
7
8
def set_year (self, year):
self._year = year
9
10
11
def get_year (self):
return self._year
12
13
14
15
16
def presentation (self):
Person.presentation(self)
print("Je suis en " + self._year + " au département "
+ self._dept + ".")
17
18
19
js = Student(22, "Jane", "Doe", "L3", "MITSIC")
js.set_name("Jane Smith")
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
19 / 23
Héritage
Héritage et accessibilité des membres
I Il
•
•
•
existe trois niveaux de restriction :
publique : accès libre par tous,
privée : accès réservé aux méthodes de la classe propriétaire,
protégée : comme privée mais accès possibles aussi aux méthodes de la classes dérivées.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
20 / 23
Héritage
Polymorphisme
I Si une classe D dérive de B alors l’interface de B est accessible sur les instances de D.
I On peut donc utiliser un D là où un B est prévu :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Group:
def __init__(self):
self._people = []
def add(self, pers):
self._people.append(pers)
print("Added: " + pers.get_name())
def remove(self, pers):
if self.is_in(pers):
self._people.remove(pers)
print("Removed: " + pers.get_name())
def is_in(self, pers):
for p in self._people:
if p == pers:
return True
return False
16
17
18
19
20
21
g = Group()
jd = Person(21, "John", "Doe")
js = Student(22, "Jane", "Smith", "L3", "MITSIC")
g.add(jd)
g.add(js)
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
21 / 23
Héritage
Interface
I Parfois, on veut définir un comportement (i.e., une interface), mais sans spécifier son
implémentation, en laissant le soin de le faire aux classes dérivées.
I Dans ce cas on peut définir ce qu’on appelle des interfaces ou classes abstraites
I Cette notion n’est pas directement supportées en Python non plus, mais il existe une
convention : on fait remonter une erreur aux méthodes qui doivent être redéfinies :
1
2
3
class Animal:
def __init__ (self, name):
self._name = name
4
5
6
1
2
3
1
2
3
def speak (self):
raise NotImplementedError()
class Cat (Animal):
def speak (self):
print(self._name + ": Miaou !")
class Dog (Animal):
def speak (self):
print(self._name + ": Ouaf !")
I Une classe qui implémente toutes les méthodes abstraites de ses classes parentes est
dite concrète.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
22 / 23
TD
1. Écrire une classe StudentGroup qui a comme attribut le niveau d’étude du groupe
et qui vérifie à l’ajout que l’étudiant·e ajouté·e est bien du bon niveau, sinon affiche
une erreur.
2. Écrire du code qui teste que la classe StudentGroup fonctionne comme attendu.
3. Écrire une classe abstraite Shape pour représenter des figures géométriques du plan,
avec : une position et la possibilité de se déplacer par translation, une méthode qui
donne sa circonférence, et une son aire.
4. Écrire des classes concrètes Circle et Square.
Pablo Rauzy (Paris 8 / LIASD)
Méthodologie de la programmation
Séance 4
23 / 23
Téléchargement