Herència ======== Per què cal herència? --------------------- - Per estendre les dades d'una classe, afegint-hi atributs: la classe SectorCircular al mòdul :download:`figures `. Vegeu `SectorCircular`__ al Python Tutor. - Per estendre el comportament d'una classe, afegint-hi mètodes: `Laberints `_. - Per especialitzar una classe: `Artròpodes i aràcnids `_. - ... __ http://pythontutor.com/live.html#code=import%20math%0A%0Aclass%20Cercle%3A%0A%20%20%20%20%0A%20%20%20%20def%20__init__%28self,%20x,%20y,%20r%29%3A%0A%20%20%20%20%20%20%20%20self.x%20%3D%20x%0A%20%20%20%20%20%20%20%20self.y%20%3D%20y%0A%20%20%20%20%20%20%20%20self.r%20%3D%20r%0A%20%20%20%20%0A%20%20%20%20def%20area%28self%29%3A%0A%20%20%20%20%20%20%20%20return%20math.pi%20*%20%28self.r%20**%202%29%0A%0A%20%20%20%20def%20mou%28self,%20x,%20y%29%3A%0A%20%20%20%20%20%20%20%20self.x%20%2B%3D%20x%0A%20%20%20%20%20%20%20%20self.y%20%2B%3D%20y%0A%0A%0Aclass%20SectorCircular%28Cercle%29%3A%0A%20%20%20%20%22%22%22%0A%20%20%20%20Classe%20derivada%20de%20Cercle%0A%20%20%20%20%22%22%22%0A%20%20%20%20%0A%20%20%20%20def%20__init__%28self,%20x,%20y,%20r,%20angle%29%3A%0A%20%20%20%20%20%20%20%20super%28%29.__init__%28x,%20y,%20r%29%0A%20%20%20%20%20%20%20%20self.angle%20%3D%20angle%0A%0A%20%20%20%20def%20area%28self%29%3A%0A%20%20%20%20%20%20%20%20return%20self.r%20**%202%20*%20self.angle%20/%202.0%0A%20%20%20%20%0A%20%20%20%20def%20area_compl%28self%29%3A%0A%20%20%20%20%20%20%20%20areac%20%3D%20super%28%29.area%28%29%0A%20%20%20%20%20%20%20%20areas%20%3D%20self.area%28%29%0A%20%20%20%20%20%20%20%20return%20areac%20-%20areas%0A%0As1%20%3D%20SectorCircular%283,%202,%2010,%200.3%29%0Aa1%20%3D%20s1.area%28%29%0Ax1%20%3D%20s1.x%0Ay2%20%3D%20s1.y%0As1.mou%28-2,%201%29%0Aa2%20%3D%20s1.area_compl%28%29&cumulative=false&curInstr=36&heapPrimitives=false&mode=display&origin=opt-live.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false Sintaxi i terminologia ---------------------- - Sintaxi: .. code:: python class B(A): sentències - ``A`` és la classe *base* o *pare*. ``A`` és una *superclasse* de ``B``. - ``B`` és la classe *derivada* o *filla*. ``B`` és una *subclasse* d'``A``. ``B`` *hereta* d'``A``. - ``B`` té tots els atributs (de classe) i mètodes d'``A``. - En ``B`` podem afegir mètodes nous o *redefinir* mètodes d'``A``. Què és l'herència? ------------------ - L'herència és un mecanisme que permet evitar repetir codi (mètodes) en una classe derivada ``B`` tal que el seu comportament és semblant al de la classe base ``A``. __init__() i herència --------------------- - Cal redefinir el mètode ``__init__()`` a la classe derivada en aquests casos: - Els objectes de la classe derivada tenen més atributs que els de la classe base. - L'operació d'instanciació de la classe derivada té un nombre o significat d'arguments diferents del de la classe base. O el que és el mateix, el nombre o significat de paràmetres del mètode ``__init__()`` de la classe derivada difereix del de la classe base. - Sempre que es redefineix el mètode ``__init__()`` de la classe derivada, cal cridar a ``__init__()`` de la classe base abans d'afegir els atributs nous. `__init__() i herència al Python Tutor `_ Exemples d'herència ------------------- - Exemples: mòduls `figures`__, `base_pol i polv`__. __ http://pythontutor.com/visualize.html#code=import+math%0A%0Aclass+Cercle%3A%0A++++%0A++++def+__init__(self,+x,+y,+r)%3A%0A++++++++self.x+%3D+x%0A++++++++self.y+%3D+y%0A++++++++self.r+%3D+r%0A++++%0A++++def+area(self)%3A%0A++++++++return+math.pi+*+(self.r+**+2)%0A%0A++++def+mou(self,+x,+y)%3A%0A++++++++self.x+%2B%3D+x%0A++++++++self.y+%2B%3D+y%0A%0A++++def+__str__(self)%3A%0A++++++++return+'centre%3D'%2B+str(+(self.x,self.y)+)+%2B+',+radi%3D'+%2B+%5C%0A++++++++++++str(self.r)%0A%0A%0Aclass+SectorCircular(Cercle)%3A%0A++++%22%22%22%0A++++Classe+derivada+de+Cercle%0A++++%22%22%22%0A++++%0A++++def+__init__(self,+x,+y,+r,+angle)%3A%0A++++++++super().__init__(x,+y,+r)%0A++++++++self.angle+%3D+angle%0A%0A++++def+area(self)%3A%0A++++++++return+self.r+**+2+*+self.angle+/+2.0%0A++++%0A++++def+__str__(self)%3A%0A++++++++return+super().__str__()+%2B+',+angle%3D'+%2B+str(self.angle)%0A%0A%0Aclass+rectangle%3A%0A++++%0A++++def+__init__(self,+x,+y,+l)%3A%0A++++++++self.x+%3D+x%0A++++++++self.y+%3D+y%0A++++++++self.l+%3D+l%0A++++%0A++++def+area(self)%3A%0A++++++++return+self.l+**+2%0A%0A++++def+mou(self,+x,+y)%3A%0A++++++++self.x+%2B%3D+x%0A++++++++self.y+%2B%3D+y%0A%0A++++def+__str__(self)%3A%0A++++++++return+'centre%3D'%2B+str(+(self.x,self.y)+)+%2B+',+costats%3D+'+%2B+str(self.l)%0A%0A%0Adef+suma_arees(e1,+e2)%3A%0A++++%22%22%22%0A++++Funci%C3%B3+polim%C3%B2rfica+que+admet+qualsevol+tipus+d'objecte+geom%C3%A8tric%0A++++(Cercles,+%C3%A0rees+circulars+i/o+quadrats)%0A++++%22%22%22%0A++++return+e1.area()+%2B+e2.area()%0A&mode=edit&origin=opt-frontend.js&cumulative=false&heapPrimitives=true&textReferences=false&showOnlyOutputs=false&py=3&rawInputLstJSON=%5B%5D __ http://pythontutor.com/visualize.html#code=class+Polinomi%3A%0A%0A+++def+__init__(self)%3A%0A++++++%22%22%22%0A++++++Crea+un+polinomi+amb+tots+els+coeficients+nuls%0A++++++%22%22%22%0A++++++self.coefs+%3D+%7B%7D%0A%0A%0A+++def+__setitem__(self,+i,+v)%3A%0A++++++%22%22%22%0A++++++Assigna+v+al+coeficient+i-%C3%A8ssim+del+polinomi.%0A++++++%22%22%22%0A++++++if+v+%3D%3D+0%3A%0A+++++++++if+i+in+self.coefs%3A%0A++++++++++++self.coefs.pop(i)%0A++++++else%3A%0A+++++++++self.coefs%5Bi%5D+%3D+v%0A++++++%0A%0A+++def+__getitem__(self,+i)%3A%0A++++++%22%22%22%0A++++++Retorna+el+coeficient+i-%C3%A8ssim+del+polinomi.%0A++++++%22%22%22%0A++++++return+self.coefs.get(i,+0)%0A++++++%0A%0A+++def+grau(self)%3A%0A++++++%22%22%22%0A++++++Retorna+el+grau+del+polinomi%3B+zero+si+%C3%A9s+el+polinomi+nul.%0A++++++%22%22%22%0A++++++if+len(self.coefs)+%3D%3D+0%3A%0A+++++++++g+%3D+0%0A++++++else%3A%0A+++++++++g+%3D+max(self.coefs.keys())%0A++++++return+g%0A%0A%0A+++def+__str__(self)%3A%0A++++++%22%22%22%0A++++++Retorna+un+string+corresponent+a+la+representaci%C3%B3+del+%0A++++++polinomi+on+la+variable+es+representa+pel+car%C3%A0cter+'x'.%0A++++++%22%22%22+%0A++++++s+%3D+''%0A++++++for+i+in+range(0,self.grau()%2B1)%3A%0A+++++++++ai+%3D+self%5Bi%5D%0A+++++++++if+ai!%3D0%3A%0A++++++++++++if+ai%3E0.0%3A%0A+++++++++++++++sgn+%3D+'%2B'%0A++++++++++++else%3A%0A+++++++++++++++sgn+%3D+''%0A++++++++++++if+i%3D%3D0%3A%0A+++++++++++++++pot+%3D''%0A++++++++++++elif+i%3D%3D1%3A%0A+++++++++++++++pot+%3D+'x'%0A++++++++++++else%3A%0A+++++++++++++++pot+%3D+'x'%2B'%5E'%2Bstr(i)%0A++++++++++++coef+%3D+str(ai)%0A++++++++++++if+i%3E0%3A%0A+++++++++++++++if+ai%3D%3D1%3A%0A++++++++++++++++++coef+%3D+''%0A+++++++++++++++elif+ai%3D%3D-1%3A%0A++++++++++++++++++coef+%3D+'-'%0A++++++++++++s+%3D+sgn+%2B+coef+%2B+pot+%2B+s%0A++++++if+s%3D%3D''%3A%0A+++++++++s+%3D+'0'%0A++++++if+s.startswith('%2B')%3A%0A+++++++++s+%3D+s%5B1%3A%5D%0A++++++return+s%0A%0A%0Aclass+PolinomiV(Polinomi)%3A%0A+++%0A+++%22%22%22%0A+++Exemples+d'%C3%BAs+de+la+classe%3A%0A+++%0A+++%3E%3E%3E+p+%3D+PolinomiV('t')%0A+++%3E%3E%3E+p%5B1%5D+%3D+4%0A+++%3E%3E%3E+p%5B2%5D+%3D+-5%0A+++%3E%3E%3E+print(p)%0A+++-5t%5E2%2B4t%0A+++%3E%3E%3E+print(p.deriva())%0A+++-10t%2B4%0A+++%3E%3E%3E+print(p.deriva().deriva())%0A+++-10%0A+++%22%22%22%0A%0A+++def+__init__(self,+nomv)%3A%0A++++++super().__init__()%0A++++++self.nomv+%3D+nomv%0A%0A+++def+__str__(self)%3A%0A++++++return+super().__str__().replace('x',+self.nomv)%0A+++++++%0A+++def+deriva(self)%3A%0A++++++d+%3D+PolinomiV(self.nomv)%0A++++++for+i+in+range(1,self.grau()%2B1)%3A%0A+++++++++d%5Bi-1%5D+%3D+self%5Bi%5D*i%0A++++++return+d%0A&mode=edit&origin=opt-frontend.js&cumulative=false&heapPrimitives=true&textReferences=false&showOnlyOutputs=false&py=3&rawInputLstJSON=%5B%5D