ebSkola

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.

SR 2.4.18. Lieto OOP pamatus SR 2.4.15. Modulāras programmas un funkcijas

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.

  1. Ieraksti class Kapteinis(Dalibnieks): un zem tā pass.
  2. Izveido objektu k = Kapteinis("Anna", 100).
  3. Izsauc tam metodi apraksts(), ko neesi klasē rakstījis.
  4. Pieraksti, no kurienes šī metode radās.
  5. Izsauc arī sanem_punktus() un pārbaudi, ka tā strādā.
  6. 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.

  1. Pievieno klasē def __init__(self, vards):.
  2. Izsauc tajā super().__init__(vards, energija=120).
  3. Pievieno zem tā self.loma = "kapteinis".
  4. Izveido objektu tikai ar vārdu un izdrukā enerģiju.
  5. Izdzēs super() izsaukumu un mēģini izdrukāt vārdu.
  6. Pieraksti, kāda kļūda radās.
  7. 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.

  1. Pievieno klasei Kapteinis metodi def sauklis(self):.
  2. Izdrukā tajā komandas saukli ar dalībnieka vārdu.
  3. Izveido otru bērna klasi Prezentetajs ar citu enerģiju.
  4. Pievieno tai metodi, kuras kapteinim nav.
  5. Mēģini izsaukt kapteinim prezentētāja metodi un izlasi kļūdu.
  6. Izveido sarakstu ar abiem objektiem un izsauc katram apraksts().
  7. 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.

  1. Izveido klasi LaikaSargs, kas manto no Dalibnieks.
  2. Uzstādi tai lielāku tempu, bet mazāku enerģiju.
  3. Pievieno tai unikālu metodi.
  4. Izveido visu trīs lomu sarakstu.
  5. 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)}")
Anna stabilitāte mazināja punktu zudumu; atlikusī enerģija 135
isinstance(anna, Dalibnieks) = True