Ügyességi játékok programozása
Pythonnal és Pygame-melChapter 12: Bevezetés az osztályok használatába
Zsákoljuk be a hasonló változókat, és keltsük életre őket!
12.1 Miért tanuljunk az osztályokról?
Minden kalandjátékban a karakternek szüksége van adatra: név, hely, erő, felemelik a kezüket, merre vették az irányt, stb. Plussz, a karakterek még dolgokat is csinálnak. Futnak, ugranak, ütnek, és beszélnek.
A mi Python kódunk, ami ezt az adatot tárolja, így kéne kinézzen:
name = "Link" sex = "Male" max_hit_points = 50 current_hit_points = 50
Annak rendje szerint, hogy tegyünk bármit is a karakterrel ,szükséges átadni ezt az adatot egy függvénynek:
def display_character(name, sex, max_hit_points, current_hit_points): print (name, sex, max_hit_points, current_hit_points)
Most már el tudod képzelni, hogyan kell nekivágni egy olyan programnak, ami változókat tárol mindenféle karakterekről, szörnyekről, tárgyakról a játékhoz. Azután létre kell hozni olyan függvényeket, amik ezeket a tárgyakat kezelik. Tonnányi adaton kell átgázolni. Hirtelen ez már nem is tűnik szórakoztatónak!
Na, várj csak, lesz ez még rosszabb! Ahogy a játék egyre nagyobb lesz, újabb mezőket kell megadnunk, hogy leírjuk a karakterünket. Ez esetben a max_speed tulajdonságot adtuk hozzá:
name = "Link" sex = "Male" max_hit_points = 50 current_hit_points = 50 max_speed = 10 def display_character(name, sex, max_hit_points, current_hit_points, max_speed): print (name, sex, max_hit_points, current_hit_points)
A fenti példában mindössze egy függvény van. De egy nagy videójátékban, többszáz függvényt kell kezelnünk, amik a főkarakterrel bánnak. Egy új mező beillesztése azt kívánja meg tőlünk, hogy átrágjuk magunkat az összes függvényen, és hozzáadjuk a paraméter listájához. Na ez jó sok munka. És talán a max_speed-t más típusú karakterekhez is hozzá kell adnunk, mint amilyen egy szörny. Ehhez jobb módszert kell találni. Valahogyan, a programunknak szüksége volna egyben kezelnie az adatmezőket, és akkor könnyebb lenne az egésszel bánni.
12.2 Egyszerű osztályok létrehozása
Sokkal jobb módja a sok adat kezelésének, ha definiálunk egy szerkezetet, ami az összes adatot kezelni fogja. Azután már adhatunk ennek a csoportba szedett információnak nevet, olyanokat, mint Character vagy Address. Ezt könnyen megtehetjük a Pythonnal és más modern nyelvvel, ha osztályt használunk.
Például, egy osztály egy karaktert reprezentál a játékban:
class Character(): name = "Link" sex = "Male" max_hit_points = 50 current_hit_points = 50 max_speed = 10 armor_amount = 8
Itt egy másik gyakori példa arra, hogy hogyan tartsa egy cím osztály, összes mezőjét egy helyen:
class Address(): name = "" line1 = "" line2 = "" city = "" state = "" zip = ""
A fenti kódban, az Address az osztály neve. A változók az osztályban, mint amilyen a name, city azok, amiket attribútumoknak vagy mezőknek hívunk. (Jegyezd meg, hogy a hasonlóságokat és különbségeket az osztály és a függvény definiálásakor.)
Más függvényhez és változóhoz képest az osztály neve nagybetűvel kezdődik. Lehetőség van arra, hogy kisbetűvel kezdjük a nevét, de az egy rossz gyakorlat.
Ahhoz, hogy jobban elképzelhessük az osztályokat és azt, ahogyan egymáshoz kapcsolódnak, a programozók gyakran készítenek diagramokat. Az ábra, ami az Address osztályhoz van, itt látható: 12.1. Figyeld meg, hogy az osztály neve van legfelül, azután pedig az attribútumok vannak felsorolva. Jobbra, minden attribútumtól van az adattípus arról, hogy szöveg vagy egész.
Az osztály kód definiálja az osztályt, de nem hoz létre egyből példányt. A kód megmondja a számítógépnek, hogy milyen mezői vannak, és azoknak mi a kezdő értéke. Ennek ellenére még nincs semmi sem megcímezve. Készíthetünk úgy osztályt, anélkül, hogy bármivel is hivatkoznánk rá, ahogyan függvényt is csinálhatunk, anélkül, hogy hívnánk. Ahhoz, hogy lásd, hogyan hozunk létre egy osztályt és mezőket, nézd meg a példát alább:
# létrehozunk egy címet homeAddress = Address() # töltsük ki a mezőket homeAddress.name = "John Smith" homeAddress.line1 = "701 N. C Street" homeAddress.line2 = "Carver Science Building" homeAddress.city = "Indianola" homeAddress.state = "IA" homeAddress.zip = "50125"
A cím osztálynak egy példányát hoztuk létre, a második sorban. Figyeld meg, hogyan használtuk az Address osztály nevét: zárójeleket tettünk utána. A változó neve bármi lehet, ami a szokásos névadási normáknak megfelel.
Ahhoz, hogy a mezőket az osztályba tegyük, a program egy pont operátort használ. Ez választja el a homeAddress-t és a mezőnevet. Nézd meg, ahogyan az 5-10-s sorok használják ezt az operátort.
Egy gyakori hiba, az osztályokkal való munka során, hogy elfelejtik specifikálni melyik példányával akarnak dolgozni az osztályból. Ha csak egy cím lett létrehozva, akkor természetes, hogy a számítógép tudni fogja melyik az. Ez egy másik eset. Nézd a következő példát:
class Address(): name = "" line1 = "" line2 = "" city = "" state = "" zip = "" # cím létrehozása my_address = Address() # Figyelem! Ez nem egy cím neve! name = "Dr. Craven" # Ez sem a cím neve! Address.name = "Dr. Craven" # Ez a helyes: my_address.name = "Dr. Craven"
Másik címet készítünk és az összes mezőt használjuk. Nézd meg az alábbi példát:
class Address(): name = "" line1 = "" line2 = "" city = "" state = "" zip = "" # Cím létrehozása homeAddress = Address() # A cím mezőinek feltöltése homeAddress.name = "John Smith" homeAddress.line1 = "701 N. C Street" homeAddress.line2 = "Carver Science Building" homeAddress.city = "Indianola" homeAddress.state = "IA" homeAddress.zip = "50125" # készítünk egy másik címet vacationHomeAddress = Address() # ennek a mezőit is feltöltjük vacationHomeAddress.name = "John Smith" vacationHomeAddress.line1 = "1122 Main Street" vacationHomeAddress.line2 = "" vacationHomeAddress.city = "Panama City Beach" vacationHomeAddress.state = "FL" vacationHomeAddress.zip = "32407" print("The client's main home is in " + homeAddress.city) print("His vacation home is in " + vacationHomeAddress.city)
A tizedik sor hozza létre az első példányát az Address osztálynak; a huszonegyedik sor pedig a második példányt. A homeAddress változó az első példányra mutat, a vacationHomeAddress változó pedig a másodikra.
A 24-29 sor tölti fel adattal a mezőket az új osztály példánynál. A 31-s sor kinyomtatja a várost a lakóhelyből, mivel a homeAddress hivatkozik rá a pont operátor előtt. A 32-s sor a vakáció alatti cím, amire a vacationHomeAddress hivatkozik a pont operátor előtt.
A példában az Address-t osztálynak hívják, mivel ez definiálja az új osztályozását az adat objektumnak. A változók a homeAddress és a vacationHomeAddress, melyek objektumok, mivel az aktuális példányra vonatkoznak, az Address osztályban. Egy egyszerű objektum definíció ugyanaz, mint egy osztály példány. Mint ahogyan Bob és Nancy az Emberiség osztályának példányai.
Azzal, hogy használjuk www.pythontutor.com-t, képesek vagyunk elképzelni a kódot (lásd lentébb). Három változó van játékban. Az egyik az Address osztály definícióra mutat. A másik két változó viszont két másik cím objektumra mutat, és azok adataira.
Egy osztályba, ha sok adatmezőt teszünk, akkor könnyű azt egy funkcióba beledobálni. A lenti kódban, a függvény paraméterként kap egy címet, és kiírja azt a képernyőre. Nem szükséges minden cím mező paraméterét megadni a függvénynek.
# Kiír egy címet a képernyőre def printAddress(address): print(address.name) # ha van egy line1 a címben, akkor kiírja if( len(address.line1) > 0 ): print (address.line1) # ha van egy line2 a címben, akkor kiírja if( len(address.line2) > 0 ): print( address.line2 ) print( address.city+", "+address.state+" "+address.zip ) printAddress( homeAddress ) print() printAddress( vacationHomeAddress )
12.3 Eljárás hozzáadása osztályhoz
Az attribútumokon túl az osztályok rendelkezhetnek eljárásokkal vagy metódusokkal. Az eljárás egy függvény, ami az osztályon belül létezik. A korábbi példát kibővítve, egy Dog(kutya) osztályt veszünk alapul, melyhez hozzáadunk egy metódust, mégpedig kutyaugatás eljárást.
class Dog(): age = 0 name = "" weight = 0 def bark(self): print("Woof")
Az eljárás definíciója a 6-7-s sorban van. A metódusok definíciója egy osztályon belül eléggé hasonlít egy függvény definíciójára. A nagy különbség a self paraméter a hatodik sorban. Az első paraméter bármely osztályon belüli metódusnál a self kell legyen. Ez akkor is szükséges, ha a metódus nem is használja.
Itt vannak a fontos dolgok, amiket fejben kell tartani, amikor eljárást készítünk egy osztályhoz:
- Az attribútomokat kell először felsorolni, azután az eljárásokat.
- Egy eljárás első paramétere a self kell legyen.
- Az eljárás definíciót egy tabulátor behúzással jelezzük.
Az eljárások meghívása hasonlóan történik, vagyis az objektum attribútumaira hivatkozunk. Lásd az alábbi kódot:
myDog = Dog() myDog.name = "Spot" myDog.weight = 20 myDog.age = 3 myDog.bark()
Az első sor a kutyát alkotja meg. A 3-5-dik sor feltölti az objektumot. A hetedik sor, meghívja a bark(ugat) függvényt. Megjegyzendő, hogy az ugatás függvénynek egy paramétere van, a self, a hívása során ez nem megy át semmin. Ez azért van, mivel az első paraméter a kutya objektumre magára vonatkozik. A színfalak mögött, a Python egy ilyen hívást futtat le:
# A példa valójában nem legális! Dog.bark(myDog)
Ha a bark függvény számára szükséges bármilyen referencia megadása az attribútomhoz, akkor az a self-t fogja referencia változóként használni. Például, megváltoztathatjuk a kutya osztályt úgyhogy akkor, amikor a kutya ugat, ki fogja írni a kutya nevét is. A lenti kódban, a név attribútum használja a pont operátort, és a self referenciát.
def bark(self): print( "Woof says", self.name )
Attribútumok a melléknevek, és az eljárások az igék. Az osztály lerajzolása így néz ki: 12.3.
12.3.1 Példa: Labda osztály
Ez a példa kód használható Python/Pygame alatt kirajzolni egy labdát. Az összes paraméter az osztályban könnyebbé teszi az adatkezelést. A diagram a Labda osztályhoz alább látható: 12.4.
class Ball(): # --- osztály attribútumok --- # labda helyzete x = 0 y = 0 # labda vektorja change_x = 0 change_y = 0 # labda mérete size = 10 # labda színe color = [255,255,255] # --- osztály eljárás függvénye --- def move(self): self.x += self.change_x self.y += self.change_y def draw(self, screen): pygame.draw.circle(screen, self.color, [self.x, self.y], self.size )
Alább van a kód, ami majd a főprogramba kell, ami majd megalkotja a labdát, és feltölti az attribútumokat:
theBall = Ball() theBall.x = 100 theBall.y = 100 theBall.change_x = 2 theBall.change_y = 1 theBall.color = [255,0,0]
Ez a kód a főciklusba való, hogy mozgassa és kirajzolja a labdát:
theBall.move() theBall.draw(screen)
12.4 Referenciák
Ezen a részen elválasztjuk az igazi programozót, attól, aki csak szeretne programozó lenni: az osztály referenciák megértése. Vess egy pillantást a következő kódra:
class Person: name = "" money = 0 bob = Person() bob.name = "Bob" bob.money = 100 nancy = Person() nancy.name = "Nancy" print(bob.name, "has", bob.money, "dollars.") print(nancy.name, "has", nancy.money, "dollars.")
A fenti kód két Személy példányát kreálja, és használja a www.pythontutor.com, hogy el tudjuk képzelni a két osztályt az ábrán 12.5.
A fenti kódban semmi új nincs. De a lentiben már annál inkább:
class Person: name = "" money = 0 bob = Person() bob.name = "Bob" bob.money = 100 nancy = bob nancy.name = "Nancy" print(bob.name, "has", bob.money, "dollars.") print(nancy.name, "has", nancy.money, "dollars.")
Látod már a különbséget a kilencedik sorban?
Gyakori félreértés, hogy amikor objektummal dolgozik valaki, azt gondolja, hogy a bob változó a Személy objektum. Ez nem az az eset. A bob változó csak a referenciája a Személy objektumnak. Ez pedig tárolja a memória címét annak, hogy hol van az objektum, és nem az objektumot magát.
Ha bob valójában az objektum lett volna, akkor a kilencedik sornak csinálnia kellett volna egy másolatot az objektumról és akkor már két objektum létezne. A program kimenete az kellene, hogy legyen, hogy Nancynak és Bobnak is 100 dollárja van. De amikor lefut, a program kimenete, a következő lesz ehelyett:
Nancy has 100 dollars. Nancy has 100 dollars.
Amit bob tartalmaz az a referenciája az objektumnak. A referenciát emellett, lehet hívni címnek, mutatónak, vagy kezelőnek is. A referencia egy cím a számítógép memóriájában, ahol az objektum tárolva van. Ez a cím hexadecimális szám, melyet, ha kiíratunk, akkor valami ilyet kapunk, hogy 0x1e504. Amikor a kilences sor fut le, akkor a cím lesz lemásolva, ahelyett, hogy a teljes objektum címére lenne mutatva. Lásd az alábbi ábrát: 12.6.
Ezt is lefuttathatjuk a www.pythontutor.com-n, hogy lássuk, hogy mely változók mutatnak ugyanarra az objektumra.
12.4.1 Függvények és referenciák
Vess egy pillantást a lenti kódra. Az első sor létre fog hozni egy függvényt, ami egy számot kap paraméterként. A money egy változó, ami egy adatmásolatot tárol, amikor arra van szükség. Ha 100-t adunk ehhez a számhoz, akkor nem változik meg a szám a bob.money-ban, a tizedik sorban. Így a kiíratott eredmény a tizenharmadik sorban 100-t fog megjeleníteni, s nem 200-t.
def giveMoney1(money): money += 100 class Person: name = "" money = 0 bob = Person() bob.name = "Bob" bob.money = 100 giveMoney1(bob.money) print(bob.money)
Ha lefuttatjuk a PythonTutor-n, akkor láthatjuk, hogy két példányunk van a money változóból. Az egyik egy másolat és helyi változója a giveMoney1 függvénynek.
Nézd meg a lenti kiegészítő kódot. Ez a kód azt fogja okozni, hogy a bob.money megnövekszik és a print parancsunk 200-t fog kiíratni.
def giveMoney2(person): person.money += 100 giveMoney2(bob) print(bob.money)
Miért lehetséges ez? Mivel a person tartalmazza az objektum memória címének másolatát, és nem az aktuális objektumot magát. Lehet erre úgy is gondolni, mint egy bankszámla számra. Szóval, ha lemásoljuk a bankszámla számot, és teszünk rá 100 dollárt, akkor Bob számlája nőni fog.
A tömb változó hasonlóan működik. Egy függvény ami tömb(lista) változót használ paraméternek, és módosítja a tömbben az értékeket, módosítani fogja ugyanazt a tömböt, amit a hívó kód alkotott. A tömb címe le van másolva, nem az egész tömb.
12.4.2 Kérdések áttekintése
- Készíts egy osztályt, ami Macskának nevezel el. Adj neki olyan attribútumokat, hogy név, szín, súly. Adj hozzá egy eljárást, amit nyávogásnak nevezel el.
- Készíts egy példányt a macska osztályból, adj értéket az attribútumoknak és hívd meg a nyávogás eljárást.
- Készíts egy osztályt, amit Szörnynek nevezel el. Adj neki név attribútumot és egy egész változót életerőnek. Készíts egy eljárást, amit életCsökkennek hívsz, aminek lesz egy paramétere, a nagyság, és annyival fog csökkenni az életerő, amennyi ez az érték. Ebben az eljárásban, legyen egy kiírás, ha az állat meghal, mikor az életereje nulla alá kerül.
12.5 Konstruktorok
Van egy szörnyű probléma a mi kutya osztályunkkal, amit lejjebb listáztunk ki. Amikor létrehozunk egy kutyát, akkor az alapértelmezett kutyának nincs neve. A kutyáknak lennie kell nevüknek! Nem engedhetjük, hogy a kutyák úgy szülessenek meg, hogy nem kapnak nevet! Mégis, az alábbi kódban egy olyan kutyánk lesz, aminek nem lesz neve sosem.
class Dog() name = "" myDog = Dog()
A Python nem akarhatja, hogy ez történjen. Ezért van az, hogy a Python osztálynak van egy speciális függvénye, amit bármikor meghívhatunk, egy osztály esetén. Azáltal, hogy egy konstruktornak nevezett függvényt használunk, a programozó képes kódot adni a példányhoz minden alkalommal, automatikusan, amikor az osztály példánya létrejön. Lásd az alábbi konstruktor példát:
class Dog(): name="" # Konstruktor # Akkor lesz meghívva, amikor egy ilyen típusú objektumot hoznak létre def __init__(self): print("A new dog is born!") # ez hozza létre a kutyát myDog = Dog()
A konstruktor a hatodik sorban indul el. Ezt el kell nevezni __init__-tel. Kettő aláhúzás van az __init__ előtt és utána is. Gyakori hiba, hogy csak egyet használnak.
A konstruktor felveszi a self értékét, az első paraméterétm, mint bármely más eljárás.
Amikor a program lefut, akkor, ki fogja írni, hogy
A new dog is born!
Amikor a kutya objektumot megalkutjok a tizedik sorban, akkor az __init__ függvény
automatikusan meghívja és kiíratja ezt az üzenetet.
Egy konstruktort lehet használni arra, hogy egy objektumot bevezessünk és megadjuk az értéket. A példa a kutya osztály, fentebb, szintén lehetővé teszi, hogy a név attribútomot üresen hagyjuk miután létrehoztuk a kutya objektumunkat. Hogyan tudnánk ezt megakadályozni? Sok objektumnak van szüksége arra, hogy értéket vegyen fel, amikor létre hozzák. A konstruktort tudjuk erre is használni. Lássuk az alábbi kódot:
class Dog(): name = "" # Konstruktor # Akkor hívja meg, amikor ilyen típust hoz létre def __init__(self, newName): self.name = newName # ezzel hozzuk létre a kutyát myDog = Dog("Spot") # írassuk ki a kutya nevét, ellenőrzésképpen print(myDog.name) # ez a sor egy hibát küld, mivel # nem lett név adva herDog = Dog()
A hatodik sorban a konstruktor függvényben most már van egy új paraméterünk , amit newName-nek nveztünk el. Ennek a paraméternek az értéke fogja felvenni a hetedik sorban megadott kutya osztály név értékét. Most már nem hozhatunk létre kutya osztályt név nélkül. A tizenhetedik sorban ezt ellenőrízzük, és erre kapunk is egy nagy kövér hibaüzenetet. Gyakori hiba, hogy ugyanúgy nevezzük el az __init__ függvény paraméterét, és azt gondoljuk, hogy majd szinkronban lesz az osztály paraméterével. Ez azonban sosem történik meg.
A következő példában két különböző változó van, amit name-nek hívnak, Ezeket kiíratjuk a 8-s és 10-s sorban. Az első name változó úgy jön létre, mint egy eljárás paraméter a hatodik sorban. Az eljárás változó el is tűnik, amint az eljárás lefutott. A második name változó attribútumként lett létrehozva a második sorban. Ez egy teljesen más változó, mint amit a hatodik sorban hoztunk létre. A self.name változó utal arra az attribútumra, mely a kutya osztály példányáé. Az attribútum addig fog létezni, amíg a kutya osztály példánya.
class Dog(): name = "Rover" # Konstruktor # ez lesz meghívva, amikor egy ilyen típust hozunk létre def __init__(self, name): # ez kiírja, hogy "Rover" print(self.name) # ez meg kiírja, hogy "Spot" print(name) # ez alakítja meg a kutyát myDog = Dog("Spot")
12.5.1 Kérdések áttekintése
- Az osztályok nevei kicsi vagy nagybetűvel kell, hogy kezdődjenek?
- Az eljárások nevei kicsi vagy nagybetűvel kell, hogy kezdődjenek?
- Az attribútumok nevei kis vagy nagybetűvel kéne, hogy kezdődjenek?
- Mit kell először listázni egy osztályban, az attribútumot vagy eljárást?
- Milyen más elnevezések vannak a referenciára?
- Milyen más elnevezés van még a példány változóra?
- Mi a neve a példánynak egy osztályban?
- Hozz létre egy osztályt Csillag néven, ami kiírja majd, hogy "Csillag születik", mindig amikor létrehozzák.
- Hozz létre egy Szörny osztályt, az életerő és a név attribútumokkal. Adj egy konstruktort az osztályhoz, ami az életerőt és a nevet feltölti adatokkal.
12.6 Leszármazás, örökítés
Másik erős jellemzője az osztályok használatának és az objektumoknak, hogy képesek örökítésre. Lehetőség van arra, hogy létrehozzunk egy osztályt, és minden attribútumot és eljárást leörökítsünk egy szülő osztályból.
Például egy program létrehozhat egy osztályt, Hajó néven, aminek minden attribútuma megvan, ami kell egy játékba.
class Boat(): tonnage = 0 name = "" isDocked = True def dock(self): if self.isDocked: print("You are already docked.") else: self.isDocked = True print("Docking") def undock(self): if not self.isDocked: print("You aren't docked.") else: self.isDocked = False print("Undocking")
Teszteljük le a kódunkat:
b = Boat() b.dock() b.undock() b.undock() b.dock() b.dock()
A kimenetek:
You are already docked. Undocking You aren't docked. Docking You are already docked.
(Ha végignézed a videót, ami ehhez a részhez tartozik, akkor észre fogod venni, hogy a hajó osztály nem fut ebben a videóban. A kód fentebb ki lett javítva, de nem javítottam át a videóban. Emlékezz majd erre, nem számít, hogy milyen egyszerű a kód, és milyen tapasztalt a programozó, szóval teszteld a kódod, mielőtt leszállítod.)
A programunknak szüksége lesz egy tengeralattjáróra. A mi tengeralattjárónk bármit megtehet, amit egy hajó is megtehet, valamint még szükségünk lesz az alámerülésre is. Az örökítés nélkül csak két lehetőségünk van.
- Először is, add hozzá a submerge (alámerülés) parancsot a hajóhoz. Ez nem egy jó ötlet, mivel nem akarjuk azt a látszatot kelteni, hogy a hajónk normális esetben le tudna süllyedni.
- Másodjára, készítenünk kell egy másolatot a Hajó osztályból, nevezzük el Tengeralattjárónak. Ebben az osztályban hozzá kell adnunk a submerge parancsot is. Ez elsőre könnyűnek tűnik, de a dolgok nehezebbek lesznek, ha változtatunk a Hajó osztályon. Egy programozónak emlékeznie kell, hogy ebben az esetben nem csak a Hajó osztályon, hanem a Tengeralattjáró osztályon is változtatni kell. Ez a kód-szinkronizálás időigényes és hibalehetőséget tartalmaz.
Szerencsére van egyszerűbb módja is. A programunkat létrehozhatjuk gyerek osztályokból amik öröklik az összes attribútumot és eljárást a szülő osztályból. A gyermek osztályhoz azután adhatunk további mezőket, és eljárásokat, ha még szükség van rá. Például:
class Submarine(Boat): def submerge(self): print("Submerge!")
Az első sor a fontos. Egyszerűen odatesszük a Hajót zárójelek közt az osztály deklarálásakor. És automatikusan fel is vette minden attribútumát és eljárását, amit az osztály tud. Ha frissítjük a Hajó osztályt, akkor a gyermek osztály, a Tengeralattjáró is automatikusan megkapja ezeket. A leszármazás ilyen egyszerű!
A következő kód le van rajzolva az 12.10 ábrán.
class Person(): name = "" class Employee(Person): job_title = "" class Customer(Person): email = "" johnSmith = Person() johnSmith.name = "John Smith" janeEmployee = Employee() janeEmployee.name = "Jane Employee" janeEmployee.job_title = "Web Developer" bobCustomer = Customer() bobCustomer.name = "Bob Customer" bobCustomer.email = "send_me@spam.com"
A Személy elhelyezése zárójelek közé a negyedik sorban és a hetedikben, a programozó arra utasította a számítógépet, hogy a Személy legyen a szülő osztálya a Dolgozóknak és a Vásárlóknak. Ez lehetővé teszi a programnak, hogy név attribútumot feltölthessék a 14 és 18 sorban.
Az eljárások is leszármaztathatók. A lenti kód ki fogja íratni, hogy "Személy létrehozva", háromszor, mivel a munkás és a dolgozó osztályok leszármaztatottak a konstruktorral a szülő osztályból:
class Person(): name = "" def __init__(self): print("Személy létrehozva") class Employee(Person): job_title = "" class Customer(Person): email = "" johnSmith = Person() janeEmployee = Employee() bobCustomer = Customer()
Az eljárásokat felülírhatja egy leszármaztatott gyermek osztály, hogy más funkciót tarthasson fenn. A lenti kódban, a gyermek osztálynak megvan a saját konstruktorha, így a szülő osztály nem fog lefutni.
class Person(): name = "" def __init__(self): print("Person created") class Employee(Person): job_title = "" def __init__(self): print("Employee created") class Customer(Person): email = "" def __init__(self): print("Customer created") johnSmith = Person() janeEmployee = Employee() bobCustomer = Customer()
Ha a programozó arra vágyik, hogy mind a szülő és a gyermek osztály eljárást lefuttassa, akkor a gyermek kifejezetten meghívhatja a szülő eljárást:
class Person(): name = "" def __init__(self): print("Person created") class Employee(Person): job_title = "" def __init__(self): Person.__init__(self) print("Employee created") class Customer(Person): email = "" def __init__(self): Person.__init__(self) print("Customer created") johnSmith = Person() janeEmployee = Employee() bobCustomer = Customer()
12.6.1 Benne van és Van neki kapcsolata
Az osztályoknak két nagyobb típusa van kapcsolat szerint. Ezek vagy kapcsolatban vannak, vagy van nekik egy kapcsolatuk..
Egy szülő osztálynak mindig általánosabbnak kell lennie, mint a gyermek osztálynak. Ezt a fajta gyermek-szülő kapcsolatot nevezik benne van egy kapcsolatbannak. Például, egy Állat nevű szülő osztálynak lehet egy Kutya nevű gyermek osztálya. A Kutya osztálynak lehet egy Pudli nevű gyermek osztálya. Másik példa, a delfin egy emlős (benne van az emlősök osztályában-a ford.) Ez visszafelé nem működik, egy emlős nem feltétlen delfin. Valamint egy Asztal osztály nem lehet a szülő osztálya a Szék osztálynak, mivel a szék nem asztal.
A másik típusú kapcsolat a van neki kapcsolata. Ezek a kapcsolatok megvalósultak a kódban az osztály attribútumok közt. Egy kutyának van neve, és így a Kutya osztálynak van egy név attribútuma. Valamint, egy személynek lehet egy kutyája, és ez leszármaztatható is, a Személy osztálynak lehet olyan attribútuma, hogy birtokol egy kutyát. A Személy osztályt nem vezethetjük le a Kutyából, mivel ez egyfajta inzultushoz is vezetne.
Nézzük meg a példa kódunkat:
- A Dolgozó egy személy.
- A Vásárló egy személy.
- Személynek van egy neve.
- Dolgozónak van egy munka megnevezése.
- Vásárlónak van egy e-mailje.
12.7 Áttekintés
12.7.1 Kvízkérdések
Click here for a multiple-choice quiz.
12.7.2 Feladatlap
Click here for the chapter worksheet.
12.7.3 Labor feladat
Click here for the chapter lab.
You are not logged in. Log in here and track your progress.
English version by Paul Vincent Craven
Spanish version by Antonio Rodríguez Verdugo
Russian version by Vladimir Slav
Turkish version by Güray Yildirim
Portuguese version by Armando Marques Sobrinho and Tati Carvalho
Dutch version by Frank Waegeman
Hungarian version by Nagy Attila
Finnish version by Jouko Järvenpää
French version by Franco Rossi
Korean version by Kim Zeung-Il
Chinese version by Kai Lin