Bonjour à tous,
Je débute complètement en python (mais j'ai d'autres langages derrière
moi) et j'ai lu une bonne partie du "dive into Python".
Du coup, j'ai eu envie de faire quelque chose qui est un peut chiant
avec certain langages : de l'héritage multiple.
voilà un exemple qui je pense nécessite un héritage multiple :
Un doctorant est à la fois un Prof et un Etudiant, qui sont eux même
des Personne :
...
Merci beaucoup
Fab
Dans le design objet de tous les jours, on a pris un peu de distance
Bonjour à tous,
Je débute complètement en python (mais j'ai d'autres langages derrière
moi) et j'ai lu une bonne partie du "dive into Python".
Du coup, j'ai eu envie de faire quelque chose qui est un peut chiant
avec certain langages : de l'héritage multiple.
voilà un exemple qui je pense nécessite un héritage multiple :
Un doctorant est à la fois un Prof et un Etudiant, qui sont eux même
des Personne :
...
Merci beaucoup
Fab
Dans le design objet de tous les jours, on a pris un peu de distance
Bonjour à tous,
Je débute complètement en python (mais j'ai d'autres langages derrière
moi) et j'ai lu une bonne partie du "dive into Python".
Du coup, j'ai eu envie de faire quelque chose qui est un peut chiant
avec certain langages : de l'héritage multiple.
voilà un exemple qui je pense nécessite un héritage multiple :
Un doctorant est à la fois un Prof et un Etudiant, qui sont eux même
des Personne :
...
Merci beaucoup
Fab
Dans le design objet de tous les jours, on a pris un peu de distance
ok, cela n'est pas très parlant pour moi.
Je pense que je vais essayer des exemple plus simples.
Sinon, sur le bout de code que j'ai posté,qu'est ce qu'on peut
redire ?
Fab
Comment décrirait-on un doctorant qui n'a plus de cours à suivre, ou
ok, cela n'est pas très parlant pour moi.
Je pense que je vais essayer des exemple plus simples.
Sinon, sur le bout de code que j'ai posté,qu'est ce qu'on peut
redire ?
Fab
Comment décrirait-on un doctorant qui n'a plus de cours à suivre, ou
ok, cela n'est pas très parlant pour moi.
Je pense que je vais essayer des exemple plus simples.
Sinon, sur le bout de code que j'ai posté,qu'est ce qu'on peut
redire ?
Fab
Comment décrirait-on un doctorant qui n'a plus de cours à suivre, ou
Bonjour à tous,
Je débute complètement en python (mais j'ai d'autres langages derrière
moi) et j'ai lu une bonne partie du "dive into Python".
Du coup, j'ai eu envie de faire quelque chose qui est un peut chiant
avec certain langages : de l'héritage multiple.
voilà un exemple qui je pense nécessite un héritage multiple :
Un doctorant est à la fois un Prof et un Etudiant, qui sont eux même
des Personne :
class Personne:
"definition d'un personne"
def __init__(self, nom, prenom):
self.nom = nom
self.prenom = prenom
def afficher_nom(self):
print self.nom+' '+self.prenom
class Etudiant(Personne):
"definition d'un etudiant"
def __init__(self, classe, nom, prenom):
Personne.__init__(self, nom, prenom)
self.classe = classe
def afficher_classe(self):
print "Classe : "+self.classe+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_classe()
class Prof(Personne):
"Un proffesseur"
def __init__(self, matiere, nom, prenom):
Personne.__init__(self, nom, prenom)
self.matiere = matiere
def afficher_matiere(self):
print "Matiere : "+self.matiere+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_matiere()
class Doctorant(Prof, Etudiant):
"une personne a la fois prof et etudiant"
def __init__(self, matiere, classe, nom, prenom):
Prof.__init__(self, matiere, nom, prenom)
Etudiant.__init__(self, classe, nom, prenom)
def afficher_statut(self):
print self.afficher_nom()
print self.afficher_matiere()
print self.afficher_classe()
a = Etudiant("3eme B", "MORIN", "Fabien")
a.afficher_statut()
b = Prof("Math", "Gilbert", "Montanier")
b.afficher_statut()
c = Doctorant("Math", "5e B", "Alain", "Aflelou")
c.afficher_statut()
--------------------------------------
et voilà la sortie :
python classe.py
MORIN Fabien
Classe : 3eme B
Gilbert Montanier
Matiere : Math
Alain Aflelou
None
Matiere : Math
None
Classe : 5e B
None
-------------------------------------
Donc ça marche un peut près si on ne tiens pas compte des "None", mais
je ne pense pas que ce soit la bonne manière de procéder, et je ne
trouve pas trop de documentation ou d'exemple à ce sujet.
napster = Doctorant('smith', 'napster', 'info 3e cycle', 'Python')
napster.__dict__
{'matiere': 'Python', 'nom': 'smith', 'classe': 'info 3e cycle',
isinstance(napster, Etudiant)
True
igor = DoctorantEtranger('Ilitch', 'igor', classe='info 3e cycle',
matiere='
igor.affiche_statut()
Ilitch, igor (Russie)
igor = DoctorantEtrangerTravailleur('Ilitch', 'igor', classe='info
3e cycle'
igor.affiche_statut()
Ilitch, igor (dispense) (Russie)
Merci beaucoup
Bonjour à tous,
Je débute complètement en python (mais j'ai d'autres langages derrière
moi) et j'ai lu une bonne partie du "dive into Python".
Du coup, j'ai eu envie de faire quelque chose qui est un peut chiant
avec certain langages : de l'héritage multiple.
voilà un exemple qui je pense nécessite un héritage multiple :
Un doctorant est à la fois un Prof et un Etudiant, qui sont eux même
des Personne :
class Personne:
"definition d'un personne"
def __init__(self, nom, prenom):
self.nom = nom
self.prenom = prenom
def afficher_nom(self):
print self.nom+' '+self.prenom
class Etudiant(Personne):
"definition d'un etudiant"
def __init__(self, classe, nom, prenom):
Personne.__init__(self, nom, prenom)
self.classe = classe
def afficher_classe(self):
print "Classe : "+self.classe+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_classe()
class Prof(Personne):
"Un proffesseur"
def __init__(self, matiere, nom, prenom):
Personne.__init__(self, nom, prenom)
self.matiere = matiere
def afficher_matiere(self):
print "Matiere : "+self.matiere+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_matiere()
class Doctorant(Prof, Etudiant):
"une personne a la fois prof et etudiant"
def __init__(self, matiere, classe, nom, prenom):
Prof.__init__(self, matiere, nom, prenom)
Etudiant.__init__(self, classe, nom, prenom)
def afficher_statut(self):
print self.afficher_nom()
print self.afficher_matiere()
print self.afficher_classe()
a = Etudiant("3eme B", "MORIN", "Fabien")
a.afficher_statut()
b = Prof("Math", "Gilbert", "Montanier")
b.afficher_statut()
c = Doctorant("Math", "5e B", "Alain", "Aflelou")
c.afficher_statut()
--------------------------------------
et voilà la sortie :
python classe.py
MORIN Fabien
Classe : 3eme B
Gilbert Montanier
Matiere : Math
Alain Aflelou
None
Matiere : Math
None
Classe : 5e B
None
-------------------------------------
Donc ça marche un peut près si on ne tiens pas compte des "None", mais
je ne pense pas que ce soit la bonne manière de procéder, et je ne
trouve pas trop de documentation ou d'exemple à ce sujet.
napster = Doctorant('smith', 'napster', 'info 3e cycle', 'Python')
napster.__dict__
{'matiere': 'Python', 'nom': 'smith', 'classe': 'info 3e cycle',
isinstance(napster, Etudiant)
True
igor = DoctorantEtranger('Ilitch', 'igor', classe='info 3e cycle',
matiere='
igor.affiche_statut()
Ilitch, igor (Russie)
igor = DoctorantEtrangerTravailleur('Ilitch', 'igor', classe='info
3e cycle'
igor.affiche_statut()
Ilitch, igor (dispense) (Russie)
Merci beaucoup
Bonjour à tous,
Je débute complètement en python (mais j'ai d'autres langages derrière
moi) et j'ai lu une bonne partie du "dive into Python".
Du coup, j'ai eu envie de faire quelque chose qui est un peut chiant
avec certain langages : de l'héritage multiple.
voilà un exemple qui je pense nécessite un héritage multiple :
Un doctorant est à la fois un Prof et un Etudiant, qui sont eux même
des Personne :
class Personne:
"definition d'un personne"
def __init__(self, nom, prenom):
self.nom = nom
self.prenom = prenom
def afficher_nom(self):
print self.nom+' '+self.prenom
class Etudiant(Personne):
"definition d'un etudiant"
def __init__(self, classe, nom, prenom):
Personne.__init__(self, nom, prenom)
self.classe = classe
def afficher_classe(self):
print "Classe : "+self.classe+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_classe()
class Prof(Personne):
"Un proffesseur"
def __init__(self, matiere, nom, prenom):
Personne.__init__(self, nom, prenom)
self.matiere = matiere
def afficher_matiere(self):
print "Matiere : "+self.matiere+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_matiere()
class Doctorant(Prof, Etudiant):
"une personne a la fois prof et etudiant"
def __init__(self, matiere, classe, nom, prenom):
Prof.__init__(self, matiere, nom, prenom)
Etudiant.__init__(self, classe, nom, prenom)
def afficher_statut(self):
print self.afficher_nom()
print self.afficher_matiere()
print self.afficher_classe()
a = Etudiant("3eme B", "MORIN", "Fabien")
a.afficher_statut()
b = Prof("Math", "Gilbert", "Montanier")
b.afficher_statut()
c = Doctorant("Math", "5e B", "Alain", "Aflelou")
c.afficher_statut()
--------------------------------------
et voilà la sortie :
python classe.py
MORIN Fabien
Classe : 3eme B
Gilbert Montanier
Matiere : Math
Alain Aflelou
None
Matiere : Math
None
Classe : 5e B
None
-------------------------------------
Donc ça marche un peut près si on ne tiens pas compte des "None", mais
je ne pense pas que ce soit la bonne manière de procéder, et je ne
trouve pas trop de documentation ou d'exemple à ce sujet.
napster = Doctorant('smith', 'napster', 'info 3e cycle', 'Python')
napster.__dict__
{'matiere': 'Python', 'nom': 'smith', 'classe': 'info 3e cycle',
isinstance(napster, Etudiant)
True
igor = DoctorantEtranger('Ilitch', 'igor', classe='info 3e cycle',
matiere='
igor.affiche_statut()
Ilitch, igor (Russie)
igor = DoctorantEtrangerTravailleur('Ilitch', 'igor', classe='info
3e cycle'
igor.affiche_statut()
Ilitch, igor (dispense) (Russie)
Merci beaucoup
Bonjour à tous,
Je débute complètement en python (mais j'ai d'autres langages derr ière
moi) et j'ai lu une bonne partie du "dive into Python".
Du coup, j'ai eu envie de faire quelque chose qui est un peut chiant
avec certain langages : de l'héritage multiple.
Bienvenue !
voilà un exemple qui je pense nécessite un héritage multiple :
Un doctorant est à la fois un Prof et un Etudiant, qui sont eux mê me
des Personne :
Quelques commentaires donc,class Personne:
Utilisez les classes "new-style", systématiquement !
class Personne(object)"definition d'un personne"
Bon on va dire que c'est un exercice mais une docstring est censée
ajouter de l'information...def __init__(self, nom, prenom):
self.nom = nom
self.prenom = prenom
def afficher_nom(self):
print self.nom+' '+self.prenom
class Etudiant(Personne):
"definition d'un etudiant"
def __init__(self, classe, nom, prenom):
Personne.__init__(self, nom, prenom)
self.classe = classe
def afficher_classe(self):
print "Classe : "+self.classe+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_classe()
Ah ! oui, c'est bien les noms des classes et méthides suivent les
recommandations de la PEP 8, je ne sais pas si c'est volontaire, au cas o ù :
http://www.python.org/dev/peps/pep-0008/
Je ne saia pas non plus si c'est une histoire de copier-coller mais la
recommandation concernant l'indentation et de quatre espaces par niveau
(pas de tabulation).
class Prof(Personne):
"Un proffesseur"
def __init__(self, matiere, nom, prenom):
Personne.__init__(self, nom, prenom)
self.matiere = matiere
def afficher_matiere(self):
print "Matiere : "+self.matiere+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_matiere()
class Doctorant(Prof, Etudiant):
"une personne a la fois prof et etudiant"
def __init__(self, matiere, classe, nom, prenom):
Prof.__init__(self, matiere, nom, prenom)
Etudiant.__init__(self, classe, nom, prenom)
def afficher_statut(self):
print self.afficher_nom()
pourquoi print ? afficher_xxx retourne None (valeur de retour par défaut
d'une fonction), donc l'instruction print va afficher "None".print self.afficher_matiere()
print self.afficher_classe()
a = Etudiant("3eme B", "MORIN", "Fabien")
a.afficher_statut()
b = Prof("Math", "Gilbert", "Montanier")
b.afficher_statut()
c = Doctorant("Math", "5e B", "Alain", "Aflelou")
c.afficher_statut()
--------------------------------------
et voilà la sortie :
python classe.py
MORIN Fabien
Classe : 3eme B
Gilbert Montanier
Matiere : Math
Alain Aflelou
None
Matiere : Math
None
Classe : 5e B
None
-------------------------------------
Donc ça marche un peut près si on ne tiens pas compte des "None", mais
cf. plus haut.je ne pense pas que ce soit la bonne manière de procéder, et je ne
trouve pas trop de documentation ou d'exemple à ce sujet.
Comme signalé dans l'autre post, il est vrai que l'héritage (tout cou rt,
ce n'est pas spécifique à l'héritage multiple), bien que parfait en
théorie (définition de la relation "est un") est souvent moins flexib le
que l'agrégation (relation "à un"). Il faut se souvenir du Zen of Pyt hon
(import this), "flat is better than nested" (plat c'est mieux
qu'imbriqué), sentence qui s'applique aussi bien à l'architecture des
modules qu'à l'arborescence des classes.
On ne peut laisser entendre cependant qu'il faut proscrire l'héritage
(simple ou multiple), par exemple, dans votre cas, si cela doit avoir un
sens de dire isinstance(aDoctorant, Personne), il faut l'utiliser.
Il y a en revanche un problème spécifique à l'héritage multiple, qui se
nomme "problème du diamant".
Suivant l'arborescence de vos classes, lorsque vous appelez la méthode
__init__ du doctorant la méthode __init__ de Personne sera appelée de ux
fois. Une fois par la méthode __init__ de Prof et l'autre fois par celle
d'Etudiant. Ici, cela ne porte pas à conséquence mais il se peut que
cela devienne très problématique et oblige plus tard à un refactori ng de
toute l'arborescence.
Python offre un moyen pour remédier à ce problème, ce sont les mé thodes
collaboratives qu'on définies avec l'utilisation de super (je vous
laisse regarder dans la doc, l'explication du mécanisme est un peu
compliquée et a à voir avec le mro, voir
http://www.python.org/download/releases/2.2.2/descrintro/#cooperation).
L'idée de base c'est de garantir que l'appel aux méthodes de chacune des
classes de l'arborescence ne se fera qu'une seule fois.
In [2]: class A(object) :
...: def collab(self) :
...: print 'A'
...:
...:
In [3]: class B(A) :
...: def collab(self) :
...: super(B, self).collab()
...: print 'B'
...:
...:
In [4]: class C(A) :
...: def collab(self) :
...: super(C, self).collab()
...: print 'C'
...:
...:
In [5]: class D(B, C) :
...: def collab(self) :
...: super(D, self).collab()
...: print 'D'
In [7]: B().collab()
A
B
In [9]: C().collab()
A
C
In [8]: D().collab()
A
C
B
D
La contre-partie c'est que vous n'êtes pas sûr que l'appel à
super(Etudiant, self).__init__ soit toujours celui de la classe
Personne. On le voit dans l'exemple précédent lorsque super(B,
self).collab() appel dans un cas A.collab et dans l'autre C.collab.
C'est encore plus évident si je défini la classe E de la façon suiv ante:
In [12]: class E(C, B) :
....: def collab(self) :
....: super(E, self).collab()
....: print 'E'
....:
....:
In [13]: D().collab()
A
C
B
D
In [14]: E().collab()
A
B
C
E
La conclusion c'est que vous ne pouvez faire aucune supposition sur les
paramètres attendus par la méthode parente appelée, donc il faut
absolument repecté une règle d'or pour les méthodes collaboratives : -
toutes les méthodes doivent avoir la même suite d'arguments positione ls
que la méthode de base,
- elle doivent toutes accepter un dictionnaire d'arguments optionels,
- tout argument n'appartenant à la liste commune lors d'un appel à une
méthode collaborative doit être nommé (l'idéal est d'avoir une va leur
par défaut pour les arguments supplémentaires).
Voilà comment réécrire votre hiérarchie avec ce principe, en ne p renant
en compte que la méthode __init__ :
class Personne(object):
"Un personne est un objet qui ...."
def __init__(self, nom, prenom, **kwargs):
"""Cette méthode est collaborative, tout argument autre que les deux
premiers doivent être nommés"""
self.nom = nom
self.prenom = prenom
class Etudiant(Personne):
def __init__(self, nom, prenom, classe, **kwargs):
super(Etudiant, self).__init__(nom, prenom, **kwargs)
self.classe = classe
class Prof(Personne):
def __init__(self, nom, prenom, matiere, **kwargs):
super(Prof, self).__init__(nom, prenom, **kwargs)
self.matiere = matiere
class Doctorant(Prof, Etudiant):
def __init__(self, nom, prenom, classe, matiere, **kwargs):
super(Doctorant, self).__init__(nom, prenom,
matiere=matiere,
classe=classe, **kwargs)
voilà, maintenant vous pouvez faire :napster = Doctorant('smith', 'napster', 'info 3e cycle', 'Python')
napster.__dict__
{'matiere': 'Python', 'nom': 'smith', 'classe': 'info 3e cycle',
'prenom': 'napster'}isinstance(napster, Etudiant)
True
etc.
Le grand intérêt de super est de pouvoir profiter pleinement de
l'extension d'implémentation d'une méthode. Ceci dit il ne faut pas
pousser ce raisonnement trop loin. Un contre exemple :
Admettons qu'on ai défini la méthode nom_complet dans la classe Perso nne
de la façon suivante:
def nom_complet(self) :
return self.nom + ', ' + self.prenom
et la méthode affiche_statut dans la classe Doctorant :
def affiche_statut(self) :
print self.nom_complet()
print self.matiere
print self.classe
Alors la définition des classes suivantes produit un résultat
particulièrement intéressant:
class EtudiantEtranger(Etudiant) :
def __init__(self, nom, prenom, pays, **kwargs):
super(EtudiantEtranger, self).__init__(nom, prenom, **kwargs)
self.pays = pays
def nom_complet(self) :
return (super(EtudiantEtranger, self).nom_complet()
+ ' (' + self.pays + ')')
class EtudiantTravailleur(Etudiant) :
def nom_complet(self) :
return (super(EtudiantTravailleur, self).nom_complet()
+ ' (dispense)')
class DoctorantEtranger(Doctorant, EtudiantEtranger) : pass
class DoctorantEtrangerTravailleur(DoctorantEtranger,
EtudiantTravailleur) : passigor = DoctorantEtranger('Ilitch', 'igor', classe='info 3e cycle ',
matiere='
Python', pays='Russie')igor.affiche_statut()
Ilitch, igor (Russie)
Python
info 3e cycleigor = DoctorantEtrangerTravailleur('Ilitch', 'igor', classe='in fo
3e cycle'
, matiere='Python', pays='Russie')igor.affiche_statut()
Ilitch, igor (dispense) (Russie)
Python
info 3e cycle
Le même résultat est moins immédiat avec l'utilisation de mixins. C eci
dit, ce schéma peut vous amener produire un grand nombre de classe, et
on sait par expérience que les grosses hiérarchies sont lourdes à
manipuler, il est donc souvent plus judicieux de transformer ce qui peut
l'être en attributs d'une classe plutôt qu'en hértitage. Dans mon
dernier exemple, "Etranger" et "Travailleur" devrait être des attributs
d'Etudiant (ou Personne), et à charge à la méthode nom_complet de c ette
classe de gérer les différents cas.
L'utilisation de mixins découle du même principe, et offre d'autres
problèmes (elle n'est pas magiquement substituable à l'héritage), e lle
utilise beaucoup en python ce que l'on appelle la délégation, mais c' est
une autre histoire...
Merci beaucoup
de rien, c'est un plaisir, je crois que je vais en profiter pour
compléter le chapitre sur les méthodes collaboratives dans mon support
de cours.
--
Maric Michaud
Bonjour à tous,
Je débute complètement en python (mais j'ai d'autres langages derr ière
moi) et j'ai lu une bonne partie du "dive into Python".
Du coup, j'ai eu envie de faire quelque chose qui est un peut chiant
avec certain langages : de l'héritage multiple.
Bienvenue !
voilà un exemple qui je pense nécessite un héritage multiple :
Un doctorant est à la fois un Prof et un Etudiant, qui sont eux mê me
des Personne :
Quelques commentaires donc,
class Personne:
Utilisez les classes "new-style", systématiquement !
class Personne(object)
"definition d'un personne"
Bon on va dire que c'est un exercice mais une docstring est censée
ajouter de l'information...
def __init__(self, nom, prenom):
self.nom = nom
self.prenom = prenom
def afficher_nom(self):
print self.nom+' '+self.prenom
class Etudiant(Personne):
"definition d'un etudiant"
def __init__(self, classe, nom, prenom):
Personne.__init__(self, nom, prenom)
self.classe = classe
def afficher_classe(self):
print "Classe : "+self.classe+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_classe()
Ah ! oui, c'est bien les noms des classes et méthides suivent les
recommandations de la PEP 8, je ne sais pas si c'est volontaire, au cas o ù :
http://www.python.org/dev/peps/pep-0008/
Je ne saia pas non plus si c'est une histoire de copier-coller mais la
recommandation concernant l'indentation et de quatre espaces par niveau
(pas de tabulation).
class Prof(Personne):
"Un proffesseur"
def __init__(self, matiere, nom, prenom):
Personne.__init__(self, nom, prenom)
self.matiere = matiere
def afficher_matiere(self):
print "Matiere : "+self.matiere+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_matiere()
class Doctorant(Prof, Etudiant):
"une personne a la fois prof et etudiant"
def __init__(self, matiere, classe, nom, prenom):
Prof.__init__(self, matiere, nom, prenom)
Etudiant.__init__(self, classe, nom, prenom)
def afficher_statut(self):
print self.afficher_nom()
pourquoi print ? afficher_xxx retourne None (valeur de retour par défaut
d'une fonction), donc l'instruction print va afficher "None".
print self.afficher_matiere()
print self.afficher_classe()
a = Etudiant("3eme B", "MORIN", "Fabien")
a.afficher_statut()
b = Prof("Math", "Gilbert", "Montanier")
b.afficher_statut()
c = Doctorant("Math", "5e B", "Alain", "Aflelou")
c.afficher_statut()
--------------------------------------
et voilà la sortie :
python classe.py
MORIN Fabien
Classe : 3eme B
Gilbert Montanier
Matiere : Math
Alain Aflelou
None
Matiere : Math
None
Classe : 5e B
None
-------------------------------------
Donc ça marche un peut près si on ne tiens pas compte des "None", mais
cf. plus haut.
je ne pense pas que ce soit la bonne manière de procéder, et je ne
trouve pas trop de documentation ou d'exemple à ce sujet.
Comme signalé dans l'autre post, il est vrai que l'héritage (tout cou rt,
ce n'est pas spécifique à l'héritage multiple), bien que parfait en
théorie (définition de la relation "est un") est souvent moins flexib le
que l'agrégation (relation "à un"). Il faut se souvenir du Zen of Pyt hon
(import this), "flat is better than nested" (plat c'est mieux
qu'imbriqué), sentence qui s'applique aussi bien à l'architecture des
modules qu'à l'arborescence des classes.
On ne peut laisser entendre cependant qu'il faut proscrire l'héritage
(simple ou multiple), par exemple, dans votre cas, si cela doit avoir un
sens de dire isinstance(aDoctorant, Personne), il faut l'utiliser.
Il y a en revanche un problème spécifique à l'héritage multiple, qui se
nomme "problème du diamant".
Suivant l'arborescence de vos classes, lorsque vous appelez la méthode
__init__ du doctorant la méthode __init__ de Personne sera appelée de ux
fois. Une fois par la méthode __init__ de Prof et l'autre fois par celle
d'Etudiant. Ici, cela ne porte pas à conséquence mais il se peut que
cela devienne très problématique et oblige plus tard à un refactori ng de
toute l'arborescence.
Python offre un moyen pour remédier à ce problème, ce sont les mé thodes
collaboratives qu'on définies avec l'utilisation de super (je vous
laisse regarder dans la doc, l'explication du mécanisme est un peu
compliquée et a à voir avec le mro, voir
http://www.python.org/download/releases/2.2.2/descrintro/#cooperation).
L'idée de base c'est de garantir que l'appel aux méthodes de chacune des
classes de l'arborescence ne se fera qu'une seule fois.
In [2]: class A(object) :
...: def collab(self) :
...: print 'A'
...:
...:
In [3]: class B(A) :
...: def collab(self) :
...: super(B, self).collab()
...: print 'B'
...:
...:
In [4]: class C(A) :
...: def collab(self) :
...: super(C, self).collab()
...: print 'C'
...:
...:
In [5]: class D(B, C) :
...: def collab(self) :
...: super(D, self).collab()
...: print 'D'
In [7]: B().collab()
A
B
In [9]: C().collab()
A
C
In [8]: D().collab()
A
C
B
D
La contre-partie c'est que vous n'êtes pas sûr que l'appel à
super(Etudiant, self).__init__ soit toujours celui de la classe
Personne. On le voit dans l'exemple précédent lorsque super(B,
self).collab() appel dans un cas A.collab et dans l'autre C.collab.
C'est encore plus évident si je défini la classe E de la façon suiv ante:
In [12]: class E(C, B) :
....: def collab(self) :
....: super(E, self).collab()
....: print 'E'
....:
....:
In [13]: D().collab()
A
C
B
D
In [14]: E().collab()
A
B
C
E
La conclusion c'est que vous ne pouvez faire aucune supposition sur les
paramètres attendus par la méthode parente appelée, donc il faut
absolument repecté une règle d'or pour les méthodes collaboratives : -
toutes les méthodes doivent avoir la même suite d'arguments positione ls
que la méthode de base,
- elle doivent toutes accepter un dictionnaire d'arguments optionels,
- tout argument n'appartenant à la liste commune lors d'un appel à une
méthode collaborative doit être nommé (l'idéal est d'avoir une va leur
par défaut pour les arguments supplémentaires).
Voilà comment réécrire votre hiérarchie avec ce principe, en ne p renant
en compte que la méthode __init__ :
class Personne(object):
"Un personne est un objet qui ...."
def __init__(self, nom, prenom, **kwargs):
"""Cette méthode est collaborative, tout argument autre que les deux
premiers doivent être nommés"""
self.nom = nom
self.prenom = prenom
class Etudiant(Personne):
def __init__(self, nom, prenom, classe, **kwargs):
super(Etudiant, self).__init__(nom, prenom, **kwargs)
self.classe = classe
class Prof(Personne):
def __init__(self, nom, prenom, matiere, **kwargs):
super(Prof, self).__init__(nom, prenom, **kwargs)
self.matiere = matiere
class Doctorant(Prof, Etudiant):
def __init__(self, nom, prenom, classe, matiere, **kwargs):
super(Doctorant, self).__init__(nom, prenom,
matiere=matiere,
classe=classe, **kwargs)
voilà, maintenant vous pouvez faire :
napster = Doctorant('smith', 'napster', 'info 3e cycle', 'Python')
napster.__dict__
{'matiere': 'Python', 'nom': 'smith', 'classe': 'info 3e cycle',
'prenom': 'napster'}
isinstance(napster, Etudiant)
True
etc.
Le grand intérêt de super est de pouvoir profiter pleinement de
l'extension d'implémentation d'une méthode. Ceci dit il ne faut pas
pousser ce raisonnement trop loin. Un contre exemple :
Admettons qu'on ai défini la méthode nom_complet dans la classe Perso nne
de la façon suivante:
def nom_complet(self) :
return self.nom + ', ' + self.prenom
et la méthode affiche_statut dans la classe Doctorant :
def affiche_statut(self) :
print self.nom_complet()
print self.matiere
print self.classe
Alors la définition des classes suivantes produit un résultat
particulièrement intéressant:
class EtudiantEtranger(Etudiant) :
def __init__(self, nom, prenom, pays, **kwargs):
super(EtudiantEtranger, self).__init__(nom, prenom, **kwargs)
self.pays = pays
def nom_complet(self) :
return (super(EtudiantEtranger, self).nom_complet()
+ ' (' + self.pays + ')')
class EtudiantTravailleur(Etudiant) :
def nom_complet(self) :
return (super(EtudiantTravailleur, self).nom_complet()
+ ' (dispense)')
class DoctorantEtranger(Doctorant, EtudiantEtranger) : pass
class DoctorantEtrangerTravailleur(DoctorantEtranger,
EtudiantTravailleur) : pass
igor = DoctorantEtranger('Ilitch', 'igor', classe='info 3e cycle ',
matiere='
Python', pays='Russie')
igor.affiche_statut()
Ilitch, igor (Russie)
Python
info 3e cycle
igor = DoctorantEtrangerTravailleur('Ilitch', 'igor', classe='in fo
3e cycle'
, matiere='Python', pays='Russie')
igor.affiche_statut()
Ilitch, igor (dispense) (Russie)
Python
info 3e cycle
Le même résultat est moins immédiat avec l'utilisation de mixins. C eci
dit, ce schéma peut vous amener produire un grand nombre de classe, et
on sait par expérience que les grosses hiérarchies sont lourdes à
manipuler, il est donc souvent plus judicieux de transformer ce qui peut
l'être en attributs d'une classe plutôt qu'en hértitage. Dans mon
dernier exemple, "Etranger" et "Travailleur" devrait être des attributs
d'Etudiant (ou Personne), et à charge à la méthode nom_complet de c ette
classe de gérer les différents cas.
L'utilisation de mixins découle du même principe, et offre d'autres
problèmes (elle n'est pas magiquement substituable à l'héritage), e lle
utilise beaucoup en python ce que l'on appelle la délégation, mais c' est
une autre histoire...
Merci beaucoup
de rien, c'est un plaisir, je crois que je vais en profiter pour
compléter le chapitre sur les méthodes collaboratives dans mon support
de cours.
--
Maric Michaud
Bonjour à tous,
Je débute complètement en python (mais j'ai d'autres langages derr ière
moi) et j'ai lu une bonne partie du "dive into Python".
Du coup, j'ai eu envie de faire quelque chose qui est un peut chiant
avec certain langages : de l'héritage multiple.
Bienvenue !
voilà un exemple qui je pense nécessite un héritage multiple :
Un doctorant est à la fois un Prof et un Etudiant, qui sont eux mê me
des Personne :
Quelques commentaires donc,class Personne:
Utilisez les classes "new-style", systématiquement !
class Personne(object)"definition d'un personne"
Bon on va dire que c'est un exercice mais une docstring est censée
ajouter de l'information...def __init__(self, nom, prenom):
self.nom = nom
self.prenom = prenom
def afficher_nom(self):
print self.nom+' '+self.prenom
class Etudiant(Personne):
"definition d'un etudiant"
def __init__(self, classe, nom, prenom):
Personne.__init__(self, nom, prenom)
self.classe = classe
def afficher_classe(self):
print "Classe : "+self.classe+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_classe()
Ah ! oui, c'est bien les noms des classes et méthides suivent les
recommandations de la PEP 8, je ne sais pas si c'est volontaire, au cas o ù :
http://www.python.org/dev/peps/pep-0008/
Je ne saia pas non plus si c'est une histoire de copier-coller mais la
recommandation concernant l'indentation et de quatre espaces par niveau
(pas de tabulation).
class Prof(Personne):
"Un proffesseur"
def __init__(self, matiere, nom, prenom):
Personne.__init__(self, nom, prenom)
self.matiere = matiere
def afficher_matiere(self):
print "Matiere : "+self.matiere+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_matiere()
class Doctorant(Prof, Etudiant):
"une personne a la fois prof et etudiant"
def __init__(self, matiere, classe, nom, prenom):
Prof.__init__(self, matiere, nom, prenom)
Etudiant.__init__(self, classe, nom, prenom)
def afficher_statut(self):
print self.afficher_nom()
pourquoi print ? afficher_xxx retourne None (valeur de retour par défaut
d'une fonction), donc l'instruction print va afficher "None".print self.afficher_matiere()
print self.afficher_classe()
a = Etudiant("3eme B", "MORIN", "Fabien")
a.afficher_statut()
b = Prof("Math", "Gilbert", "Montanier")
b.afficher_statut()
c = Doctorant("Math", "5e B", "Alain", "Aflelou")
c.afficher_statut()
--------------------------------------
et voilà la sortie :
python classe.py
MORIN Fabien
Classe : 3eme B
Gilbert Montanier
Matiere : Math
Alain Aflelou
None
Matiere : Math
None
Classe : 5e B
None
-------------------------------------
Donc ça marche un peut près si on ne tiens pas compte des "None", mais
cf. plus haut.je ne pense pas que ce soit la bonne manière de procéder, et je ne
trouve pas trop de documentation ou d'exemple à ce sujet.
Comme signalé dans l'autre post, il est vrai que l'héritage (tout cou rt,
ce n'est pas spécifique à l'héritage multiple), bien que parfait en
théorie (définition de la relation "est un") est souvent moins flexib le
que l'agrégation (relation "à un"). Il faut se souvenir du Zen of Pyt hon
(import this), "flat is better than nested" (plat c'est mieux
qu'imbriqué), sentence qui s'applique aussi bien à l'architecture des
modules qu'à l'arborescence des classes.
On ne peut laisser entendre cependant qu'il faut proscrire l'héritage
(simple ou multiple), par exemple, dans votre cas, si cela doit avoir un
sens de dire isinstance(aDoctorant, Personne), il faut l'utiliser.
Il y a en revanche un problème spécifique à l'héritage multiple, qui se
nomme "problème du diamant".
Suivant l'arborescence de vos classes, lorsque vous appelez la méthode
__init__ du doctorant la méthode __init__ de Personne sera appelée de ux
fois. Une fois par la méthode __init__ de Prof et l'autre fois par celle
d'Etudiant. Ici, cela ne porte pas à conséquence mais il se peut que
cela devienne très problématique et oblige plus tard à un refactori ng de
toute l'arborescence.
Python offre un moyen pour remédier à ce problème, ce sont les mé thodes
collaboratives qu'on définies avec l'utilisation de super (je vous
laisse regarder dans la doc, l'explication du mécanisme est un peu
compliquée et a à voir avec le mro, voir
http://www.python.org/download/releases/2.2.2/descrintro/#cooperation).
L'idée de base c'est de garantir que l'appel aux méthodes de chacune des
classes de l'arborescence ne se fera qu'une seule fois.
In [2]: class A(object) :
...: def collab(self) :
...: print 'A'
...:
...:
In [3]: class B(A) :
...: def collab(self) :
...: super(B, self).collab()
...: print 'B'
...:
...:
In [4]: class C(A) :
...: def collab(self) :
...: super(C, self).collab()
...: print 'C'
...:
...:
In [5]: class D(B, C) :
...: def collab(self) :
...: super(D, self).collab()
...: print 'D'
In [7]: B().collab()
A
B
In [9]: C().collab()
A
C
In [8]: D().collab()
A
C
B
D
La contre-partie c'est que vous n'êtes pas sûr que l'appel à
super(Etudiant, self).__init__ soit toujours celui de la classe
Personne. On le voit dans l'exemple précédent lorsque super(B,
self).collab() appel dans un cas A.collab et dans l'autre C.collab.
C'est encore plus évident si je défini la classe E de la façon suiv ante:
In [12]: class E(C, B) :
....: def collab(self) :
....: super(E, self).collab()
....: print 'E'
....:
....:
In [13]: D().collab()
A
C
B
D
In [14]: E().collab()
A
B
C
E
La conclusion c'est que vous ne pouvez faire aucune supposition sur les
paramètres attendus par la méthode parente appelée, donc il faut
absolument repecté une règle d'or pour les méthodes collaboratives : -
toutes les méthodes doivent avoir la même suite d'arguments positione ls
que la méthode de base,
- elle doivent toutes accepter un dictionnaire d'arguments optionels,
- tout argument n'appartenant à la liste commune lors d'un appel à une
méthode collaborative doit être nommé (l'idéal est d'avoir une va leur
par défaut pour les arguments supplémentaires).
Voilà comment réécrire votre hiérarchie avec ce principe, en ne p renant
en compte que la méthode __init__ :
class Personne(object):
"Un personne est un objet qui ...."
def __init__(self, nom, prenom, **kwargs):
"""Cette méthode est collaborative, tout argument autre que les deux
premiers doivent être nommés"""
self.nom = nom
self.prenom = prenom
class Etudiant(Personne):
def __init__(self, nom, prenom, classe, **kwargs):
super(Etudiant, self).__init__(nom, prenom, **kwargs)
self.classe = classe
class Prof(Personne):
def __init__(self, nom, prenom, matiere, **kwargs):
super(Prof, self).__init__(nom, prenom, **kwargs)
self.matiere = matiere
class Doctorant(Prof, Etudiant):
def __init__(self, nom, prenom, classe, matiere, **kwargs):
super(Doctorant, self).__init__(nom, prenom,
matiere=matiere,
classe=classe, **kwargs)
voilà, maintenant vous pouvez faire :napster = Doctorant('smith', 'napster', 'info 3e cycle', 'Python')
napster.__dict__
{'matiere': 'Python', 'nom': 'smith', 'classe': 'info 3e cycle',
'prenom': 'napster'}isinstance(napster, Etudiant)
True
etc.
Le grand intérêt de super est de pouvoir profiter pleinement de
l'extension d'implémentation d'une méthode. Ceci dit il ne faut pas
pousser ce raisonnement trop loin. Un contre exemple :
Admettons qu'on ai défini la méthode nom_complet dans la classe Perso nne
de la façon suivante:
def nom_complet(self) :
return self.nom + ', ' + self.prenom
et la méthode affiche_statut dans la classe Doctorant :
def affiche_statut(self) :
print self.nom_complet()
print self.matiere
print self.classe
Alors la définition des classes suivantes produit un résultat
particulièrement intéressant:
class EtudiantEtranger(Etudiant) :
def __init__(self, nom, prenom, pays, **kwargs):
super(EtudiantEtranger, self).__init__(nom, prenom, **kwargs)
self.pays = pays
def nom_complet(self) :
return (super(EtudiantEtranger, self).nom_complet()
+ ' (' + self.pays + ')')
class EtudiantTravailleur(Etudiant) :
def nom_complet(self) :
return (super(EtudiantTravailleur, self).nom_complet()
+ ' (dispense)')
class DoctorantEtranger(Doctorant, EtudiantEtranger) : pass
class DoctorantEtrangerTravailleur(DoctorantEtranger,
EtudiantTravailleur) : passigor = DoctorantEtranger('Ilitch', 'igor', classe='info 3e cycle ',
matiere='
Python', pays='Russie')igor.affiche_statut()
Ilitch, igor (Russie)
Python
info 3e cycleigor = DoctorantEtrangerTravailleur('Ilitch', 'igor', classe='in fo
3e cycle'
, matiere='Python', pays='Russie')igor.affiche_statut()
Ilitch, igor (dispense) (Russie)
Python
info 3e cycle
Le même résultat est moins immédiat avec l'utilisation de mixins. C eci
dit, ce schéma peut vous amener produire un grand nombre de classe, et
on sait par expérience que les grosses hiérarchies sont lourdes à
manipuler, il est donc souvent plus judicieux de transformer ce qui peut
l'être en attributs d'une classe plutôt qu'en hértitage. Dans mon
dernier exemple, "Etranger" et "Travailleur" devrait être des attributs
d'Etudiant (ou Personne), et à charge à la méthode nom_complet de c ette
classe de gérer les différents cas.
L'utilisation de mixins découle du même principe, et offre d'autres
problèmes (elle n'est pas magiquement substituable à l'héritage), e lle
utilise beaucoup en python ce que l'on appelle la délégation, mais c' est
une autre histoire...
Merci beaucoup
de rien, c'est un plaisir, je crois que je vais en profiter pour
compléter le chapitre sur les méthodes collaboratives dans mon support
de cours.
--
Maric Michaud
Bonjour à tous,
Je débute complètement en python (mais j'ai d'autres langages derrière
moi) et j'ai lu une bonne partie du "dive into Python".
Du coup, j'ai eu envie de faire quelque chose qui est un peut chiant
avec certain langages : de l'héritage multiple.
voilà un exemple qui je pense nécessite un héritage multiple :
Un doctorant est à la fois un Prof et un Etudiant, qui sont eux même
des Personne :
class Personne:
"definition d'un personne"
def __init__(self, nom, prenom):
self.nom = nom
self.prenom = prenom
def afficher_nom(self):
print self.nom+' '+self.prenom
p =Personne('Morin', 'Fabien')
p
<class '__main__.Personne' {Fabien Morin} at 4032ef6cd>
print p
Fabien Morin
class Etudiant(Personne):
"definition d'un etudiant"
def __init__(self, classe, nom, prenom):
Personne.__init__(self, nom, prenom)
class Prof(Personne):
"Un proffesseur"
def __init__(self, matiere, nom, prenom):
Personne.__init__(self, nom, prenom)
self.matiere = matiere
def afficher_matiere(self):
print "Matiere : "+self.matiere+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_matiere()
class Doctorant(Prof, Etudiant):
"une personne a la fois prof et etudiant"
def __init__(self, matiere, classe, nom, prenom):
Prof.__init__(self, matiere, nom, prenom)
Etudiant.__init__(self, classe, nom, prenom)
def afficher_statut(self):
print self.afficher_nom()
print self.afficher_matiere()
print self.afficher_classe()
d = Doctorant("Einstein", "Albert", "terminale", "Sciences")
d
<class '__main__.Doctorant' {Einstein Albert - matière: Sciences -
d2 = Doctorant2('Marx', 'Groucho', 'absurdité', 'maternelle')
d2
<class '__main__.Doctorant2' {Marx Groucho - classe: maternelle -
mais
je ne pense pas que ce soit la bonne manière de procéder, et je ne
trouve pas trop de documentation ou d'exemple à ce sujet.
Bonjour à tous,
Je débute complètement en python (mais j'ai d'autres langages derrière
moi) et j'ai lu une bonne partie du "dive into Python".
Du coup, j'ai eu envie de faire quelque chose qui est un peut chiant
avec certain langages : de l'héritage multiple.
voilà un exemple qui je pense nécessite un héritage multiple :
Un doctorant est à la fois un Prof et un Etudiant, qui sont eux même
des Personne :
class Personne:
"definition d'un personne"
def __init__(self, nom, prenom):
self.nom = nom
self.prenom = prenom
def afficher_nom(self):
print self.nom+' '+self.prenom
p =Personne('Morin', 'Fabien')
p
<class '__main__.Personne' {Fabien Morin} at 4032ef6cd>
print p
Fabien Morin
class Etudiant(Personne):
"definition d'un etudiant"
def __init__(self, classe, nom, prenom):
Personne.__init__(self, nom, prenom)
class Prof(Personne):
"Un proffesseur"
def __init__(self, matiere, nom, prenom):
Personne.__init__(self, nom, prenom)
self.matiere = matiere
def afficher_matiere(self):
print "Matiere : "+self.matiere+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_matiere()
class Doctorant(Prof, Etudiant):
"une personne a la fois prof et etudiant"
def __init__(self, matiere, classe, nom, prenom):
Prof.__init__(self, matiere, nom, prenom)
Etudiant.__init__(self, classe, nom, prenom)
def afficher_statut(self):
print self.afficher_nom()
print self.afficher_matiere()
print self.afficher_classe()
d = Doctorant("Einstein", "Albert", "terminale", "Sciences")
d
<class '__main__.Doctorant' {Einstein Albert - matière: Sciences -
d2 = Doctorant2('Marx', 'Groucho', 'absurdité', 'maternelle')
d2
<class '__main__.Doctorant2' {Marx Groucho - classe: maternelle -
mais
je ne pense pas que ce soit la bonne manière de procéder, et je ne
trouve pas trop de documentation ou d'exemple à ce sujet.
Bonjour à tous,
Je débute complètement en python (mais j'ai d'autres langages derrière
moi) et j'ai lu une bonne partie du "dive into Python".
Du coup, j'ai eu envie de faire quelque chose qui est un peut chiant
avec certain langages : de l'héritage multiple.
voilà un exemple qui je pense nécessite un héritage multiple :
Un doctorant est à la fois un Prof et un Etudiant, qui sont eux même
des Personne :
class Personne:
"definition d'un personne"
def __init__(self, nom, prenom):
self.nom = nom
self.prenom = prenom
def afficher_nom(self):
print self.nom+' '+self.prenom
p =Personne('Morin', 'Fabien')
p
<class '__main__.Personne' {Fabien Morin} at 4032ef6cd>
print p
Fabien Morin
class Etudiant(Personne):
"definition d'un etudiant"
def __init__(self, classe, nom, prenom):
Personne.__init__(self, nom, prenom)
class Prof(Personne):
"Un proffesseur"
def __init__(self, matiere, nom, prenom):
Personne.__init__(self, nom, prenom)
self.matiere = matiere
def afficher_matiere(self):
print "Matiere : "+self.matiere+"n"
def afficher_statut(self):
Personne.afficher_nom(self)
self.afficher_matiere()
class Doctorant(Prof, Etudiant):
"une personne a la fois prof et etudiant"
def __init__(self, matiere, classe, nom, prenom):
Prof.__init__(self, matiere, nom, prenom)
Etudiant.__init__(self, classe, nom, prenom)
def afficher_statut(self):
print self.afficher_nom()
print self.afficher_matiere()
print self.afficher_classe()
d = Doctorant("Einstein", "Albert", "terminale", "Sciences")
d
<class '__main__.Doctorant' {Einstein Albert - matière: Sciences -
d2 = Doctorant2('Marx', 'Groucho', 'absurdité', 'maternelle')
d2
<class '__main__.Doctorant2' {Marx Groucho - classe: maternelle -
mais
je ne pense pas que ce soit la bonne manière de procéder, et je ne
trouve pas trop de documentation ou d'exemple à ce sujet.
Juste à titre d'exemple, comment modélise-tu, dans ton système, le cas
d'un Etudiant qui, après avoir obtenu ses diplômes, est embauché comme
Professeur ? Avec une relation 'est un', tu va devoir créer une nouvelle
instance de Professeur, et recopier les attributs de l'instance de
Etudiant. Ce qui pose (au moins) deux problèmes : d'une part, une
duplication de données (puisqu'a priori, dans un système d'information,
on conserve les 'archives' durant un certain temps), et d'autre part une
non-identité entre deux instances de Personne représentant la même
personne.
Bref (et pour surenchérir sur Maric), la modélisation 'correcte' (NB:
relire la toute première proposition de ce post et nuancer en
fonction...) est d'utiliser une notion de rôle. Etudiant et professeur
sont deux des (potentiellement nombreux) rôles qu'une même personne peut
jouer dans sa vie - parfois simultanément, comme par exemple dans le cas
des doctorants. Ce n'est donc pas une relation 'est un' (puisque cette
relation peut évoluer durant le cycle de vie d'un objet Personne), mais
'a un' - ce qui se traduit généralement par une solution du type
[composition ou aggrégation] + délégation.
Juste à titre d'exemple, comment modélise-tu, dans ton système, le cas
d'un Etudiant qui, après avoir obtenu ses diplômes, est embauché comme
Professeur ? Avec une relation 'est un', tu va devoir créer une nouvelle
instance de Professeur, et recopier les attributs de l'instance de
Etudiant. Ce qui pose (au moins) deux problèmes : d'une part, une
duplication de données (puisqu'a priori, dans un système d'information,
on conserve les 'archives' durant un certain temps), et d'autre part une
non-identité entre deux instances de Personne représentant la même
personne.
Bref (et pour surenchérir sur Maric), la modélisation 'correcte' (NB:
relire la toute première proposition de ce post et nuancer en
fonction...) est d'utiliser une notion de rôle. Etudiant et professeur
sont deux des (potentiellement nombreux) rôles qu'une même personne peut
jouer dans sa vie - parfois simultanément, comme par exemple dans le cas
des doctorants. Ce n'est donc pas une relation 'est un' (puisque cette
relation peut évoluer durant le cycle de vie d'un objet Personne), mais
'a un' - ce qui se traduit généralement par une solution du type
[composition ou aggrégation] + délégation.
Juste à titre d'exemple, comment modélise-tu, dans ton système, le cas
d'un Etudiant qui, après avoir obtenu ses diplômes, est embauché comme
Professeur ? Avec une relation 'est un', tu va devoir créer une nouvelle
instance de Professeur, et recopier les attributs de l'instance de
Etudiant. Ce qui pose (au moins) deux problèmes : d'une part, une
duplication de données (puisqu'a priori, dans un système d'information,
on conserve les 'archives' durant un certain temps), et d'autre part une
non-identité entre deux instances de Personne représentant la même
personne.
Bref (et pour surenchérir sur Maric), la modélisation 'correcte' (NB:
relire la toute première proposition de ce post et nuancer en
fonction...) est d'utiliser une notion de rôle. Etudiant et professeur
sont deux des (potentiellement nombreux) rôles qu'une même personne peut
jouer dans sa vie - parfois simultanément, comme par exemple dans le cas
des doctorants. Ce n'est donc pas une relation 'est un' (puisque cette
relation peut évoluer durant le cycle de vie d'un objet Personne), mais
'a un' - ce qui se traduit généralement par une solution du type
[composition ou aggrégation] + délégation.
Juste à titre d'exemple, comment modélise-tu, dans ton système, le cas
d'un Etudiant qui, après avoir obtenu ses diplômes, est embauché comme
Professeur ? Avec une relation 'est un', tu va devoir créer une
nouvelle instance de Professeur, et recopier les attributs de
l'instance de Etudiant. Ce qui pose (au moins) deux problèmes : d'une
part, une duplication de données (puisqu'a priori, dans un système
d'information, on conserve les 'archives' durant un certain temps), et
d'autre part une non-identité entre deux instances de Personne
représentant la même personne.
Bref (et pour surenchérir sur Maric), la modélisation 'correcte' (NB:
relire la toute première proposition de ce post et nuancer en
fonction...) est d'utiliser une notion de rôle. Etudiant et professeur
sont deux des (potentiellement nombreux) rôles qu'une même personne
peut jouer dans sa vie - parfois simultanément, comme par exemple dans
le cas des doctorants. Ce n'est donc pas une relation 'est un'
(puisque cette relation peut évoluer durant le cycle de vie d'un objet
Personne), mais 'a un' - ce qui se traduit généralement par une
solution du type [composition ou aggrégation] + délégation.
bjr,
N'étant pas un maître de l'objet mais ayant joué avec un langage acteur
je vois l'avantage de ces relations mais je ne vois pas comment l'écrire
pouvez vous (la cantonade) éclairer ma lanterne ?
Juste à titre d'exemple, comment modélise-tu, dans ton système, le cas
d'un Etudiant qui, après avoir obtenu ses diplômes, est embauché comme
Professeur ? Avec une relation 'est un', tu va devoir créer une
nouvelle instance de Professeur, et recopier les attributs de
l'instance de Etudiant. Ce qui pose (au moins) deux problèmes : d'une
part, une duplication de données (puisqu'a priori, dans un système
d'information, on conserve les 'archives' durant un certain temps), et
d'autre part une non-identité entre deux instances de Personne
représentant la même personne.
Bref (et pour surenchérir sur Maric), la modélisation 'correcte' (NB:
relire la toute première proposition de ce post et nuancer en
fonction...) est d'utiliser une notion de rôle. Etudiant et professeur
sont deux des (potentiellement nombreux) rôles qu'une même personne
peut jouer dans sa vie - parfois simultanément, comme par exemple dans
le cas des doctorants. Ce n'est donc pas une relation 'est un'
(puisque cette relation peut évoluer durant le cycle de vie d'un objet
Personne), mais 'a un' - ce qui se traduit généralement par une
solution du type [composition ou aggrégation] + délégation.
bjr,
N'étant pas un maître de l'objet mais ayant joué avec un langage acteur
je vois l'avantage de ces relations mais je ne vois pas comment l'écrire
pouvez vous (la cantonade) éclairer ma lanterne ?
Juste à titre d'exemple, comment modélise-tu, dans ton système, le cas
d'un Etudiant qui, après avoir obtenu ses diplômes, est embauché comme
Professeur ? Avec une relation 'est un', tu va devoir créer une
nouvelle instance de Professeur, et recopier les attributs de
l'instance de Etudiant. Ce qui pose (au moins) deux problèmes : d'une
part, une duplication de données (puisqu'a priori, dans un système
d'information, on conserve les 'archives' durant un certain temps), et
d'autre part une non-identité entre deux instances de Personne
représentant la même personne.
Bref (et pour surenchérir sur Maric), la modélisation 'correcte' (NB:
relire la toute première proposition de ce post et nuancer en
fonction...) est d'utiliser une notion de rôle. Etudiant et professeur
sont deux des (potentiellement nombreux) rôles qu'une même personne
peut jouer dans sa vie - parfois simultanément, comme par exemple dans
le cas des doctorants. Ce n'est donc pas une relation 'est un'
(puisque cette relation peut évoluer durant le cycle de vie d'un objet
Personne), mais 'a un' - ce qui se traduit généralement par une
solution du type [composition ou aggrégation] + délégation.
bjr,
N'étant pas un maître de l'objet mais ayant joué avec un langage acteur
je vois l'avantage de ces relations mais je ne vois pas comment l'écrire
pouvez vous (la cantonade) éclairer ma lanterne ?