Que faut-il pour définir une classe ?
En python, seul le constructeur est obligatoire, et se définit avec le nom réservé __init__
Il n'y a pas besoin de destructeurs explicites, les objets sont libérés en l'absence de référence active pointant sur eux.
class Duree:
"""une classe pour manipuler des durées temporelles, en heures/minutes/secondes
"""
def __init__(self,nbsec):
# attribut public
self.total = nbsec
# attribut privé
self.__bof = 0
def heures(self):
return self.total//3600
def minutes(self):
return (self.total % 3600)//60
def secondes(self):
return self.total % 60
def __repr__(self):
return "%02d:%02d:%02d"%(self.heures(),self.minutes(),self.secondes())
def __add__(self,other):
return Duree(self.total+other.total)
def __sub__(self,other):
return Duree(abs(self.total-other.total))
a = Duree(4567)
b = Duree(10010)
print("a =",a,"; b =",b)
print("a+b =",a+b)
print("a-b =",a-b)
De même que __init__ est une méthode spéciale, on peut redéfinir certaines méthodes suivantes pour avoir des effets particuliers :
Les opérateurs mathématiques peuvent être surchargés pour prendre comme arguments des objets de la classe considérée, en redéfinissant les méthodes suivantes:
Le lien d'héritage en python se définit de façon classique, par surcharge des méthodes.
class Rectangle:
def __init__(self,largeur,longueur):
self.large = largeur
self.long = longueur
def aire(self):
return self.large*self.long
def get_largeur(self):
return self.large
def get_longueur(self):
return self.long
def __repr__(self):
return str(self.long)+"x"+str(self.large)
class Carre(Rectangle):
def __init__(self,cote):
Rectangle.__init__(self,cote,cote)
self.blabla = 0
def get_cote(self):
return self.get_longueur()
r = Rectangle(10,30)
c = Carre(10)
print(r)
print(c)
print(c.get_cote())
Les objets sont définis par référence, comme toutes les données mutables en python.
Comment faire pour avoir des objets similaires distincts ? Il faut faire des copies :
import copy
c = copy.copy(a)
c is a
Mais cette copie est "superficielle", elle ne fait que recopier les attributs. Si l'attribut est lui-même un pointeur sur un objet structuré, il n'est pas distinct.
Il faut alors utiliser une "copie profonde" :
c = copy.deepcopy(a)
On peut faire hériter une classe de plusieurs classes pour récupérer tous les traits et attributs en les combinant.
En cas de conflit pour une méthode, la priorité est sur la première classe héritée.
class A:
def m(self):
print("appel de A.m")
class B(A):
def m(self):
print("appel de B.m")
class C(A):
def m(self):
print("appel de C.m")
# héritage multiple
class D(B,C):
pass
a = D()
a.m()