Knyga/Klasės: Skirtumas tarp puslapio versijų
Nėra keitimo santraukos |
Nėra keitimo santraukos |
||
| 1 eilutė: | 1 eilutė: | ||
{{navigation |previous=Derinimas |next=Rekursinės funkcijos}} | {{navigation |previous=Derinimas |next=Rekursinės funkcijos}} | ||
=== Ką išmoksi šiame skyriuje? === | |||
* Kas yra klasė ir objektas | |||
* Kaip sukurti savo klasę su kintamaisiais ir metodais | |||
* Kuo skiriasi numatytasis ir deklaruotasis konstruktoriai | |||
* Kaip naudoti <code>__init__()</code> ir <code>self</code> | |||
* Kaip perduoti parametrus kuriant objektą | |||
* Kaip veikia metodai objektuose ir kada jie keičia objekto būseną | |||
* Kuo skiriasi skirtingų objektų kintamieji | |||
=== Klasės === | === Klasės === | ||
| 31 eilutė: | 40 eilutė: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Kaip matome, kintamieji neturi jokios reikšmės, | Kaip matome, kintamieji neturi jokios reikšmės, tai rodo raktažodis <code>None</code>. Norint šios klasės pagrindu sukurti objektą, mes turime iškviesti numatytąjį konstruktorių: | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
Jonas = Žmogus() | Jonas = Žmogus() | ||
| 69 eilutė: | 78 eilutė: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Kaip matome, konstruktorius reikalauja dviejų parametrų - '''vardas''' ir '''amžius'''. Jis taip pat turi | Kaip matome, konstruktorius reikalauja dviejų parametrų - '''vardas''' ir '''amžius'''. Jis taip pat turi parametrą '''self''', kuris nurodo į konkretų objektą – jo perduoti nereikiaeikia, jis leidžia konstruktoriui pasiekti objekto kintamuosius ir metodus prieš priskiriant objektą kintamajam. Kurdami objektą '''''Jonas''''', konstruktoriui mes paduodame tekstinę eilutę su vardu “Jonas” bei skaičių “14”. Kodo vykdymo pabaigoje bus išspausdintos objekto '''''Jonas''''' kintamųjų '''vardas''' ir '''amžius''' vertės - “Vardas: Jonas” ir “Amžius: 14”. Taigi, deklaruotasis konstruktorius, priešingai negu numatytasis, sukūrė objektą su programuotojo numatytomis kintamųjų reikšmėmis. Deklaruotasis konstruktorius gali turėti faktiškai neribotą kiekį parametrų, kuriuos gali priimti ir priskirti objekto kintamiesiems, tačiau, pagal gerąją praktiką, konstruktorius neturėtų turėti daugiau kaip 5 parametrų. | ||
💡 self visada nurodo į konkretų objektą, kuris kviečia metodą. Tai leidžia metodams pasiekti ir keisti objekto kintamuosius. | |||
Paminėtina ir tai, kad konstruktoriuje galima nurodyti numatytąsias reikšmes kintamiesiems, kurios bus priskirtos, jeigu programuotojas nepaduoda jokių parametrų, kviesdamas deklaruotąjį konstruktorių: <syntaxhighlight lang="python"> | Paminėtina ir tai, kad konstruktoriuje galima nurodyti numatytąsias reikšmes kintamiesiems, kurios bus priskirtos, jeigu programuotojas nepaduoda jokių parametrų, kviesdamas deklaruotąjį konstruktorių: <syntaxhighlight lang="python"> | ||
| 85 eilutė: | 96 eilutė: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Kode aprašytas konstruktorius | Kode aprašytas konstruktorius priima du parametrus - vardas ir amžius, bet abu parametrai turi priskirtą numatytąją reikšmę - "''Bevardis''" ir ''0''. Tą indikuoja lygybės ženklas ir pageidaujama tekstinė eilutė (parametro vardas atveju) ir skaičius (parametro amžius atveju). Kodo vykdymo pabaigoje bus išspausdintos objekto Jonas kintamųjų Vardas ir Amžius vertės - “Vardas: Bevardis” ir “Amžius: 0”. Kadangi deklaruotasis konstruktrius negavo jokių parametrų, jis kintamiesiems priskyrė konstruktoriuje nurodytas numatytąsias vertes. | ||
💡 Klasės pavadinimas su skliaustais (pvz., Žmogus()) iškviečia jos konstruktorių ir sukuria objektą. | |||
==== Klasės metodų naudojimas ==== | ==== Klasės metodų naudojimas ==== | ||
| 136 eilutė: | 149 eilutė: | ||
Objekto Petras vardas po pakeitimo: None | Objekto Petras vardas po pakeitimo: None | ||
Kaip matai, objektui ''Petras'' priklausantis kintamasis ''vardas'' nebuvo pakeistas, nors mes ir pakeitėme kintamojo ''vardas'' reikšmę objekte ''Jonas''. Taip pasireiškia viena iš pagrindinių objekto savybių - kiekvienas objektas turi savo kintamuosius ir jų reikšmės yra atskirtos nuo kitų, tos pačios klasės pagrindu sukurtų objektų. Yra tam tikrų šios taisyklės išimčių, bet jas | Kaip matai, objektui ''Petras'' priklausantis kintamasis ''vardas'' nebuvo pakeistas, nors mes ir pakeitėme kintamojo ''vardas'' reikšmę objekte ''Jonas''. Taip pasireiškia viena iš pagrindinių objekto savybių - kiekvienas objektas turi savo kintamuosius ir jų reikšmės yra atskirtos nuo kitų, tos pačios klasės pagrindu sukurtų objektų. Yra tam tikrų šios taisyklės išimčių, bet jas pakalbėsime kitose temose. | ||
💡 Kiekvienas objektas turi savo duomenis – kai vienam objektui pakeičiame kintamojo reikšmę, kitų objektų duomenys lieka nepakitę. | |||
{{navigation |previous=Derinimas |next=Rekursinės funkcijos}} | {{navigation |previous=Derinimas |next=Rekursinės funkcijos}} | ||
Dabartinė 16:11, 6 rugpjūčio 2025 versija
Ką išmoksi šiame skyriuje?
- Kas yra klasė ir objektas
- Kaip sukurti savo klasę su kintamaisiais ir metodais
- Kuo skiriasi numatytasis ir deklaruotasis konstruktoriai
- Kaip naudoti
__init__()irself - Kaip perduoti parametrus kuriant objektą
- Kaip veikia metodai objektuose ir kada jie keičia objekto būseną
- Kuo skiriasi skirtingų objektų kintamieji
Klasės
Pitonas yra objektinė programavimo kalba, tad, iš principo, viskas, kas naudojama pitone yra objektas, su visais jam priklausančiais kitamaisiais bei metodais. Klasė yra tarsi brėžinys/maketas (angliškai - blueprint), pagal kurį yra kuriami objektai. Klasėse yra apibrėžiama objekto struktūra (kintamieji) ir jo funkcionalumas (angliškai - behaviour). Klasės inkapsuliuoja duomenis ir funkcionalumus, skatina kodo pernaudojamumą ir moduliškumą.
Inkapsuliacija – tai vienas iš pagrindinių objektinio programavimo principų ir viena svarbiausių klasės užduočių. Programavime inkapsuliacija suprantama, kaip tiesioginės prieigos prie tam tikrų duomenų ar metodų apribojimas. Paprastai pasakius, tai reiškia, kad tam tikra informacija ar funkcionalumas nėra prieinamas vartotojui, naudojančiam objektą, pavyzdžiui, apribojama vartotojo teisė matyti/keisti objekto ID kintamąjį, sukūrimo laiką, ir pan. Inkapsuliacijos naudojimas yra itin svarbus, kai yra siekiama apsaugoti tam tikrus jautrius duomenis nuo pakeitimų.
Atkreipikime dėmesį į tai, kad yra naudojamas naujas terminas – metodas. Metodu vadiname funkciją, kai ji priklauso kokiai nors klasei. Tai yra nuo seno įsišaknijęs terminas, leidžiantis atskirti, kam priklauso funkcija – ar ji yra taikoma pati savaime, ar priklauso klasei/objektui.
Klasės struktūra
Kiekviena klasė pitone prasideda nuo raktažodžio class. Kode klasės deklaravimas atrodo taip:
class MyClass
Susipažinome su klasės deklaravimu, bet kas sudaro pačią klasę? Klasė susideda iš jai priklausančių kintamųjų ir metodų. Iš esmės kiekviena klasė turės savo kintamuosius ir metodus, kadangi tuščia klasė (išskyrus tam tikrus specifinius atvejus) iš esmės neturi jokios prasmės ir neatlieka savo pagrindinės funkcijos – skatinti kodo pernaudojamumą bei moduliškumą. Tikra klasė turėtų atrodyti maždaug taip:
class Žmogus:
vardas = None
amžius = None
def pakeisti_vardą(self, naujas_vardas):
self.vardas= naujas_vardas
Kaip matome, yra deklaruota klasė Žmogus, ji turi du kintamuosius vardas ir amžius bei metodą pakeisti_vardą(), kuris kaip parametrą (naujas_vardas) priima tekstinę eilutę su vardu ir juo pakeičia klasės kintamąjį vardas. Viskas kas yra aprašyta po klasės deklaracija, priklauso klasei, nesvarbu, ar tai būtų kintamieji, ar metodai.
Objekto sukūrimas
Kiekviena klasė turi specialų metodą, pavadinimu konstruktorius (angliškai - constructor), kurio paskirtis – kurti objektus, atitinkančios tos klasės struktūrą, priskirti jo kintamiesiems vertes. Jis visada iškviečiamas kaip metodas su klasės pavadinimu - klasėsPavadinimas(). Konstruktorius yra dviejų rūšių - numatytasis ir deklaruotas.
Numatytasis konstruktorius – tai konstruktorius, kurį kiekvienai klasei suteikia pats pitonas, jeigu programuotojas nedeklaruoja kitokio konstruktoriaus. Pagrindinė šio konstruktoriaus paskirtis – sukurti objektą, tačiau jis neatlieka jokių kitų veiksmų - nepriskiria jokių kintamųjų verčių, jų neapdoroja ir pan. Tai reiškia, kad tuo atveju, jeigu klasės kintamieji neturi priskirtų verčių, tai ir sukurto objekto kintamieji tų verčių neturės. Pavyzdžiui turime klasę:
class Žmogus:
vardas = None
amžius = None
Kaip matome, kintamieji neturi jokios reikšmės, tai rodo raktažodis None. Norint šios klasės pagrindu sukurti objektą, mes turime iškviesti numatytąjį konstruktorių:
Jonas = Žmogus()
Tokiu būdu sukuriamas Žmogus tipo objektas ir priskiriamas kintamajam Jonas. Objektas Jonas turi visus klasės kintamuosius, t. y. Jonas turi vardas ir amžius, bei jų abiejų reikšmės turėtų sutapti su klasėje nurodytomis reikšmėmis. Tą patikrinti galime tokiu būdu:
class Žmogus:
vardas = None
amžius = 24
Jonas = Žmogus()
print(f"Vardas: {Jonas.vardas}")
print(f"Amžius: {Jonas.amžius}")
Šis kodas į terminalą išves dvi eilutes:
Vardas: None Amžius: 24
Taigi, matome, kad objektas Jonas turi tuos pačius kintamuosius ir reikšmes, kokios yra priskirtos kintamiesiems klasėje.
Deklaruotasis konstruktorius – tai yra konstruktorius, kuris yra aprašomas programuotojo. Priešingai negu numatytasis konstruktorius, šis konstruktorius gali atlikti papildomus veiksmus kuriant objektą, pavyzdžiui, užpildo objekto kintamuosius duomenimis, atlieka papildomus veiksmus (išspausdina kintamųjų reikšmes, iškviečia reikalingus metodus, sukuria papildomus objektus ir pan.). Tokio tipo konstruktorius kode yra deklaruojamas pavadinimu __init__(), o per jo parametrus nurodome, kokias reikšmes šis konstruktorius priima ir jas priskiria kuriamo objekto kintamiesiems:
class Žmogus:
vardas = None
amžius = 24
def __init__(self, vardas, amžius):
self.vardas = vardas
self.amžius = amžius
Jonas = Žmogus()
print(f“Vardas: {Jonas.vardas}”)
print(f"Amžius: {Jonas.amžius}")
Kaip matome, konstruktorius reikalauja dviejų parametrų - vardas ir amžius. Jis taip pat turi parametrą self, kuris nurodo į konkretų objektą – jo perduoti nereikiaeikia, jis leidžia konstruktoriui pasiekti objekto kintamuosius ir metodus prieš priskiriant objektą kintamajam. Kurdami objektą Jonas, konstruktoriui mes paduodame tekstinę eilutę su vardu “Jonas” bei skaičių “14”. Kodo vykdymo pabaigoje bus išspausdintos objekto Jonas kintamųjų vardas ir amžius vertės - “Vardas: Jonas” ir “Amžius: 14”. Taigi, deklaruotasis konstruktorius, priešingai negu numatytasis, sukūrė objektą su programuotojo numatytomis kintamųjų reikšmėmis. Deklaruotasis konstruktorius gali turėti faktiškai neribotą kiekį parametrų, kuriuos gali priimti ir priskirti objekto kintamiesiems, tačiau, pagal gerąją praktiką, konstruktorius neturėtų turėti daugiau kaip 5 parametrų.
💡 self visada nurodo į konkretų objektą, kuris kviečia metodą. Tai leidžia metodams pasiekti ir keisti objekto kintamuosius.
Paminėtina ir tai, kad konstruktoriuje galima nurodyti numatytąsias reikšmes kintamiesiems, kurios bus priskirtos, jeigu programuotojas nepaduoda jokių parametrų, kviesdamas deklaruotąjį konstruktorių:
class Žmogus:
vardas = None
amžius = 24
def __init__(self, vardas="Bevardis", amžius=0):
self.vardas = vardas
self.amžius = amžius
Jonas = Žmogus()
print(f"Vardas: {Jonas.vardas}")
print(f"Amžius: {Jonas.amžius}")
Kode aprašytas konstruktorius priima du parametrus - vardas ir amžius, bet abu parametrai turi priskirtą numatytąją reikšmę - "Bevardis" ir 0. Tą indikuoja lygybės ženklas ir pageidaujama tekstinė eilutė (parametro vardas atveju) ir skaičius (parametro amžius atveju). Kodo vykdymo pabaigoje bus išspausdintos objekto Jonas kintamųjų Vardas ir Amžius vertės - “Vardas: Bevardis” ir “Amžius: 0”. Kadangi deklaruotasis konstruktrius negavo jokių parametrų, jis kintamiesiems priskyrė konstruktoriuje nurodytas numatytąsias vertes.
💡 Klasės pavadinimas su skliaustais (pvz., Žmogus()) iškviečia jos konstruktorių ir sukuria objektą.
Klasės metodų naudojimas
Kaip jau minėjau anksčiau, klasės gali turėti savo metodus. Metodai taip pat yra pasiekiami objekto, ir gali būti naudojami:
class Žmogus:
vardas = None
amžius = 24
def pakeisti_vardą(self, naujas_vardas):
self.vardas = naujas_vardas
Jonas = Žmogus()
print(f"Vardas iki pakeitimo: {Jonas.vardas}")
Jonas.pakeisti_vardą(“Jonas”)
print(f"Vardas po pakeitimo: {Jonas.vardas}")
Šis kodas taip pat išves dvi eilutes, vardo reikšmę prieš pakeisti_vardą() metodo kvietimą, ir po jo:
Vardas iki pakeitimo: None Vardas po pakeitimo: Jonas
Svarbu paminėti tai, kad vardas yra pakeičiamas tik objekto "Jonas" kontekste, t. y., jeigu turėsime objektą "Petras", objekto Jonas iškviesta funkcija pakeisti_vardą("Jonas"), ji nepakeis kintamojo vardas objekte Petras. Pažiūrėkime, kaip tai atrodo kode:
class Žmogus:
vardas = None
amžius = None
def pakeisti_vardą(self, naujas_vardas):
self.vardas = naujas_vardas
Jonas = Žmogus()
Petras = Žmogus()
print(f"Objekto Jonas vardas iki pakeitimo: {Jonas.vardas}")
print(f"Objekto Petras vardas iki pakeitimo: {Petras.vardas}")
Jonas.pakeisti_vardą("Jonas")
print(f"Objekto Jonas vardas po pakeitimo: {Jonas.vardas}")
print(f"Objekto Petras vardas po pakeitimo: {Petras.vardas}")
Šis kodas išves keturias eilutes, abiejų objektų kintamojo vardas reikšmę prieš pakeisti_vardą() metodo kvietimą, ir po jo:
Objekto Jonas vardas iki pakeitimo: None Objekto Petras vardas iki pakeitimo: None Objekto Jonas vardas po pakeitimo: Jonas Objekto Petras vardas po pakeitimo: None
Kaip matai, objektui Petras priklausantis kintamasis vardas nebuvo pakeistas, nors mes ir pakeitėme kintamojo vardas reikšmę objekte Jonas. Taip pasireiškia viena iš pagrindinių objekto savybių - kiekvienas objektas turi savo kintamuosius ir jų reikšmės yra atskirtos nuo kitų, tos pačios klasės pagrindu sukurtų objektų. Yra tam tikrų šios taisyklės išimčių, bet jas pakalbėsime kitose temose.
💡 Kiekvienas objektas turi savo duomenis – kai vienam objektui pakeičiame kintamojo reikšmę, kitų objektų duomenys lieka nepakitę.