11.4 Mantošana un super()
Stundas uzdevums: Apgūt klašu hierarhiju, izveidojot specializētas bērna klases ar mantotu un papildinātu uzvedību.
70 min plāns: Teorija un paraugs (~10 min) · 1. uzdevums (~15 min) - izveido bērna klasi · 2. uzdevums (~25 min) - izsauc vecāku konstruktoru ar super() · 3. uzdevums (~20 min) - pievieno bērnam savu metodi. Papildu uzdevumu sāc tikai tad, ja pārējie trīs ir gatavi.
Pirms sāc: atver savu klasi Dalibnieks no 11.3 stundas - tā kļūs par vecāku klasi visām specializētajām lomām.
Teorija: Mantošana - kods atkārtoti lietojams
Mantošana ļauj izveidot specializētas klases no vispārējām. Vecāku klase satur kopīgo loģiku, bērna klase pievieno specifisko.
class Dalibnieks:
def __init__(self, vards, energija=100, temps=10):
self.vards = vards
self.energija = energija
self.temps = temps
def gajiens(self, merkis):
merkis.energija -= self.temps
class Prezentetajs(Dalibnieks):
def __init__(self, vards, idejas=50):
# Izsauc vecāku konstruktoru
super().__init__(vards, energija=80, temps=5)
self.idejas = idejas # papildu atribūts
def prezentacija(self, merkis):
if self.idejas >= 10:
self.idejas -= 10
merkis.energija -= 25
print(f"{self.vards} parāda slaidu! ({merkis.vards} -25)")
else:
print("Pietrūkst ideju!")
class Kapteinis(Dalibnieks):
def __init__(self, vards):
super().__init__(vards, energija=150, temps=18)
self.stabilitate = 5
# Pārraksta vecāku metodi (override)
def sanem_punktus(self, b):
b = max(0, b - self.stabilitate) # stabilitāte mazina punktu zudumu
super().sanem_punktus(b)
m = Prezentetajs("Jānis")
b = Kapteinis("Anna")
m.prezentacija(b)
isinstance(m, Dalibnieks) atgriež True, jo Prezentetajs ir Dalibnieks.
Praktiskie uzdevumi
1. uzdevums -
Izveido bērna klasi
Beigās jaunā klase mantos visu no vecāku klases.
- Ieraksti
class Kapteinis(Dalibnieks):un zem tāpass. - Izveido objektu
k = Kapteinis("Anna", 100). - Izsauc tam metodi
apraksts(), ko neesi klasē rakstījis. - Pieraksti, no kurienes šī metode radās.
- Izsauc arī
sanem_punktus()un pārbaudi, ka tā strādā. - Izdrukā
isinstance(k, Dalibnieks).
Gatavs, kad: bērna objektam strādā visas vecāku metodes, un isinstance atgriež True.
2. uzdevums -
Izsauc vecāku konstruktoru ar super()
Beigās bērna klase varēs uzstādīt savas noklusējuma vērtības.
- Pievieno klasē
def __init__(self, vards):. - Izsauc tajā
super().__init__(vards, energija=120). - Pievieno zem tā
self.loma = "kapteinis". - Izveido objektu tikai ar vārdu un izdrukā enerģiju.
- Izdzēs
super()izsaukumu un mēģini izdrukāt vārdu. - Pieraksti, kāda kļūda radās.
- Ieliec
super()atpakaļ.
Gatavs, kad: ar super() objektam ir gan vārds, gan enerģija 120; bez tā - AttributeError.
3. uzdevums -
Pievieno bērnam savu metodi
Beigās katrai lomai būs sava spēja.
- Pievieno klasei
Kapteinismetodidef sauklis(self):. - Izdrukā tajā komandas saukli ar dalībnieka vārdu.
- Izveido otru bērna klasi
Prezentetajsar citu enerģiju. - Pievieno tai metodi, kuras kapteinim nav.
- Mēģini izsaukt kapteinim prezentētāja metodi un izlasi kļūdu.
- Izveido sarakstu ar abiem objektiem un izsauc katram
apraksts(). - Pieraksti vienu secinājumu: ko mantošana ietaupa salīdzinājumā ar kopēšanu.
Gatavs, kad: abas lomas dala kopīgās metodes, bet katrai ir sava spēja, kuras otrai nav.
Papildu uzdevums - Pievieno trešo lomu
Ja pamatdarbs ir gatavs, paplašini hierarhiju.
- Izveido klasi
LaikaSargs, kas manto noDalibnieks. - Uzstādi tai lielāku tempu, bet mazāku enerģiju.
- Pievieno tai unikālu metodi.
- Izveido visu trīs lomu sarakstu.
- Izdrukā katras lomas enerģiju ciklā.
Gatavs, kad: sarakstā ir trīs dažādas lomas, un katrai ir savas sākuma vērtības.
Biežākās kļūdas
- Aizmirsts super().__init__(): Bērna konstruktoram NEPIECIEŠAMS izsaukt vecāku, citādi atribūti netiks iestatīti.
- Pārrakstīta metode neizsauc super(): Ja vajag papildināt (nevis aizstāt) - vienmēr
super().method(). - Diamond problem vairākkārtējā mantošanā: Sarežģīts MRO. Izvairies, ja iespējams.
Koda piemērs
class Dalibnieks:
def __init__(self, vards, energija=100, temps=10):
self.vards = vards
self.energija = energija
self.temps = temps
class Kapteinis(Dalibnieks):
def __init__(self, vards):
super().__init__(vards, energija=150, temps=18)
self.stabilitate = 5
def sanem_punktus(self, b):
b = max(0, b - self.stabilitate)
self.energija = max(0, self.energija - b)
print(f"{self.vards} stabilitāte mazināja punktu zudumu; atlikusī enerģija {self.energija}")
anna = Kapteinis("Anna")
anna.sanem_punktus(20) # stabilitāte samazina zudumu par 5 punktiem
print(f"isinstance(anna, Dalibnieks) = {isinstance(anna, Dalibnieks)}")
isinstance(anna, Dalibnieks) = True