Transcript Dedovanje

Python - OOP
Dedovanje
Pogosto uporabljani postopki
Imamo razred Ulomek
Denimo, da z ulomki zelo pogosto izvajamo določen postopek
npr. jim spremenimo predznak
Napišemo ustrezno funkcijo
Vedno, ko želimo ulomkom spreminjati predznak, moramo
napisati to funkcijo
Naredimo iz nje knjižnico – "zaprimo v svoj razred"
Ampak to ni "objektno"
Znanje spreminjanja predznaka je lastno ulomku– objektu
Ulomek (objekt) naj bi znala spremeniti predznak
Odzvati se metodi spremeniPredznak:
nekUlomek.spremeniPredznak()
Ni problem, dopišemo metodo
Popravljati dobro preizkušen razred?
... Do not fix, until you are completely desperate …
2
Dedovanje
"razširjanje" objektov
Naredimo načrt za razred boljših ulomkov
Boljši: Znajo spremeniti predznak
class BoljsiUlomek(Ulomek)
Vsaka boljši ulomek "zna" vse, kar zna običajni ulomek iz razreda
Ulomek in morda še kaj
Ima ista stanja/lastnosti
Morebiti tudi dodatna
Dedovanje
Izpeljani razred podeduje vse lastnosti
In vse metode
3
Razred BoljsiUlomek
class BoljsiUlomek(Ulomek) :
''' naredimo nov razred "boljših ulomkov" '''
def spremeniPredznak(self) :
# Vsaka boljši ulomek si zna
# spremeniti predznak
pom = Ulomek(-1, 1)
self.pomnoži(pom)
# metoda pomnoži je podedovana iz razreda Ulomek
4
Uporaba Boljšega ulomka
boUl = BoljsiUlomek(2,3) # "ustvarimo" boljši ulomek
navadniUl = Ulomek(2, 3) # navadni ulomek
#izpis
boUl.izpis() # metoda izpis je podedovana!
navadniUl.izpis()
# spremenimo predznak navadnega ulomka
navadniUl.pomnozi(Ulomek(-1,1)) # "čaramo"
# spremenimo predznak 'boljšega' ulomka
boUl.spremeniPredznak() # pri "boljših" ulomkih je zadeva
elegantnejša
#izpis
boUl.izpis()
navadniUl.izpis()
5
Dedovanje
Izpeljava novih razredov iz obstoječih
Uvajanje dodatnih metod
Lahko tudi dodatne lastnosti (podatki)
Primer:
matrike
Seštevanje, odštevanje, množenje
Kvadratne matrike / class KvMatrike(Matrike)
Ker je razred izpeljan – ni potrebno na novo pisati
metod za seštevanje, odštevanje, množenje
Možne dodatne operacije
Inverz, deljenje, …
6
Dedovanje
Hierarhična zgradba razredov
Vrhnji objekt
object
Iz njega izpeljani vsi drugi razredi
Če ne napišemo class NovR(stRazred) …
class NovR :
class NovR(object) :
Razred object
Ima metodo __str__(self)
Zato jo "imajo" vsi razredi
Jo podedujejo
“specializacija” objektov
"razširjanje" razredov
7
Zajci dobijo imena
Kasneje ugotovimo, da bi bilo dobro za zajce
voditi še njihovo starost. Dodamo še datum
rojstva.
Prejšnjič – ko smo potrebovali ime, smo šli
popravljati razred
Sedaj pa naredimo nov razred, razred Pametnih
Zajcev, ki vedo, kdaj so rojeni!
In seveda znajo povedati, koliko so stari
Novi razred:
class PametniZajec(Zajec) :
8
Nove lastnosti
No, pravzaprav le ena – datumRojstva, ki bo tipa
Datum
__init__
Nastaviti tisto, kar počne __init__ v Zajec, in še
nastaviti datum
def __init__(self) :
Zajec.__init__(self) # kličemo 'nadrejeni' konstruktor
self.datumRoj = Datum()
9
__init__
In kaj če na __init__ pozabimo?
Uporabi se podedovana!
Kaj pa, če je še nadrejeni razred nima
Jo zagotovo ima
Jo je podedoval iz object
Seveda je verjetno neuporabna (ne ve za
lastnosti …)
10
Dedovanje
Sestavi razred Zlatnik, ki deduje iz razreda
Kovanec. Zlatnik ima poleg osnovnih lastnosti
kovanca podano še gostoto materiala, iz
katerega je izdelan, čistočo zlata (podano z
realnim številom med 0 in 1) in vrednost
čistega zlata na masno enoto. Razred naj
pozna tudi metodo Vrednost(), ki vrne
vrednost zlatnika.
11
Dedovanje
"razširjanje" objektov
Naredimo načrt za razred Zlatnik
Kovanec s posebnimi lastnostmi
class Zlatnik(Kovanec)
Vsaka zlatnik "je in zna" vse, kar zna kovanec in morda še kaj
Vrednost čistega zlata je enaka za VSE zlatnike
razredna spremenljivka
12
Konstante
Mimogrede …
V razredu Kvader
MIN_DOL_STR = 1
gre za konstanto
V Pythonu konstant načeloma ni
So le spremenljivke
Vedno lahko spremenimo
A dogovor – če je ime z velikimi črkami!
PUSTI PRI MIRU!!
13
Razredne spremenljivke
14
Razredne spremenljivke/lastnosti
V nekaterih drugih jezikih
Statične spremenljivke
Enaka vrednost za vse objekte nekega razreda
Npr. minimalna in maksimalna teža zajca
Skupni del serijske številke
Definiramo jih izven vseh metod
…
15
Razredne lastnosti
Razredne /statične (ker niso vezane na objekt) lastnosti
obstajajo neodvisno od obstoja objekta tega razreda
Le en primerek za cel razred!
Uporabimo tudi npr. za števec ustvarjenih objektov
16
Razredne spremenljivke
class Foo :
x = 42
def __init__(self, z) :
self.y = z
x: statična lastnost, y: objektna (nestatična) lastnost
Statične lastnosti: vsebovane v razredu, objektne lastnosti: v objektih.
Vsak objekt vsebuje svojo kopijo objektnih lastnosti, vsaka statična lastnost pa vedno
obstaja v eni sami kopiji.
t1 = Foo(42)
t2 = Foo(30)
Dva objekta - dve kopiji lastnosti y, po eno v vsakem objektu. Ker je lastnost x statična,
vedno obstaja v eni sami kopiji, tudi če nimamo nobenih objektov razreda Foo:
17
Uporaba statičnih spremenljivk
Različne konstante
Enolična identifikacija
Objekt naj ima svojo serijsko številko
Denimo, da so te številke zaporedne
Vedeti, katera je bila dodeljena zadnja
Zadnja dodeljena številka: ni lastnost objekta, ampak cele skupine
objektov
Vedno, ko je določen podatek skupen za vse objekte tega razreda
Kako vemo, ali naj bo lastnost statična ali objektna?
Statične lastnosti so tiste, ki so skupne za celoten razred – niso
posebna lastnost enega (ali nekaj) primerkov objektov tega razreda.
18
Statične lastnosti - naslavljanje
Naslavljanje
ime_objekta.ime_lastnosti ali
ime_razreda.ime_lastnosti
Praviloma:
ime_razreda.ime_lastnosti
Izogibamo se
ime_objekta.ime_lastnosti, saj ta
lastnost ni vezana na objekt!
Ni potrebno, da bi sploh obstajal kak objekt te vrste
19
Zajec
Radi bi vedeli, koliko zajcev imamo
Števec ustvarjenih objektov
NI lastnost posameznega zajca
SKUPNA lastnost
kolikoZajcev = 0;
Na začetku 0
Spreminjamo takrat, ko ustvarimo novega zajca
V konstruktorju!
Serijska številka naj bo zagotovo enolična
Določimo jo le enkrat – ob rojstvu (konstruktor)
ZAJEC_n (če je to n-ti zajec)
20
Zgled uporabe
>>>
>>> mZ = ZajecNov()
>>> mZ.PovejSerijsko()
'ZAJEC_1'
>>> ZajecNov.KolikoZajcev()
1
>>> tZ = ZajecNov()
>>> tZ.PovejSerijsko()
'ZAJEC_2'
>>> ZajecNov.KolikoZajcev()
2
>>>
21
ZajecNov
class ZajecNov :
# SKUPNE KONSTANTE
OSNOVA_SERIJSKA = "ZAJEC_"
MIN_TEŽA = 0 # minimalna teža
MAX_TEŽA = 10 # maksimalna teža
# SKUPNE SPREMENLJIVKE
kolikoZajcev = 0
22
ZajecNov
# konstruktor
def __init__(self, sp = True, teža = 1.0) :
self.spol = sp
if teža <= ZajecNov.MIN_TEŽA :
raise Exception('ne morem ustvariti zajca s težo '
+ str(teža))
if teža > ZajecNov.MAX_TEŽA :
raise Exception('Zajec je pretežak: ' + str(teža))
# če smo tu, je teža med MIN_TEŽA in MAX_TEŽA
self.masa = teža
# naredili smo novega zajca, povečamo število
ZajecNov.kolikoZajcev += 1
# določimo serisko številko
self.serijska = ZajecNov.OSNOVA_SERIJSKA +
str(ZajecNov.kolikoZajcev)
23
ZajecNov
# get/set metode
def PovejTezo(self) :
# težo bomo povedali le na 0.5 kg natančno
tezaKg = int(self.masa)
decim = int((self.masa - tezaKg) * 10)
if decim < 3 : return tezaKg + 0.0
if decim < 8 : return tezaKg + 0.5
return tezaKg + 1.0
def SpremeniTezo(self, novaTeza) :
# smislena nova teza je le med MIN_TEŽA in MAX_TEŽA
if MIN_TEŽA < novaTeza <= MAX_TEŽA :
self.masa = novaTeza;
return True # sprememba uspela
# v nasprotnem primeru NE spremenimo teže
# in javimo, da spremembe nismo naredili
return False
def PovejSerijsko(self) :
return self.serijska;
24
ZajecNov
def KolikoZajcev() :
return ZajecNov.kolikoZajcev
# def SpremeniSerijsko(self, s) : serijska se ne spremeni!!!
def PovejIme(self):
return self.ime
def JeSamec(self) :
return self.spol
# ker se spol naknadno NE spremeni, metode za
# spreminjanje spola sploh ne ponudimo uporabniku!
25
PRIMERI DEDOVANJA
26
Dedovanje
Sestavi razred Zlatnik, ki deduje iz razreda
Kovanec. Zlatnik ima poleg osnovnih lastnosti
kovanca podano še gostoto materiala, iz
katerega je izdelan, čistočo zlata (podano z
realnim številom med 0 in 1) in vrednost
čistega zlata na masno enoto. Razred naj
pozna tudi metodo Vrednost(), ki vrne
vrednost zlatnika.
27
Zlatnik
class Zlatnik(Kovanec)
# razredne spremenljivke definiramo izven __init__
vrednostCistegaZlata = 125.4 # za vse zlatnike je to enako!
def __init__(self, r, v, g, č) :
Kovanec.__init__(self, r, v) # nastavimo polmer in visina
self.gostota = g
self.cistost = č
# "SET" metode
nastaviPolmer(self, r) # podedovana
nastaviVisino(self, visina) # podedovana
def nastaviGostoto(self, x) :
def nastaviCistost(self, x) :
def nastaviVrednostCistegaZlata(v) # vrednost lahko spreminjamo tudi,
# če še ni nobenega zlatnika!
# "GET" metode
povejPolmer(self) # podedovana
povejVisino(self) # podedovana
def povejGostoto(self)
def povejCistost(self)
def povejVrednostCistegaZlata(self) # vrednost lahko zvemo tudi,
# če še ni nobenega zlatnika!
# str
def __str__(self) # podedovana str metoda nam ne ustreza!
# "znanje"
volumen(self) # podedovana
povrsina(self) # podedovana
def vrednost(self)
28
Iz muhe slon
Ne, iz muhe ne bomo naredili slona, ampak pri
nas zajci postanejo ovce
Pri nas se je oglasil bogati Rus, ki je bil tako
navdušen nad našim programom za vodenje
farme zajcev, da hoče, da mu zanj pripravimo
podoben program
Posebno nad metodo meNapojiti() je bil navdušen!
A žal on ne vodi farme zajcev, ampak farmo ovac.
Poleg tega, da ovce redi za zakol, prodaja tudi
njihove kožuhe, zato bi rad, da vodimo še barvo
njihovega kožuha.
29
Osnova: razred ZajecNov
Kakšne spremembe so potrebne
Napačne lastnosti
OSNOVA_SERIJSKA ni OK
Prav tako MAX_TEZA
Dodati lastnosti
Barva kožuha
Get/set metodi
denimo, da si tudi ovce barvajo kožuhe
Popraviti konstruktor
Dodati metodo __str__
V razredu ZajecNov smo nanjo pozabili!
30
Prekrite metode
V predniku (neposrednem ali posrednem)
definirana metoda nam ne ustreza
Predefiniranje: prekrite metode
Overriding
Enaka metoda kot pri predniku – velja naša
definicija
31
Zgled
Urejen seznam
Denimo, da velikokrat potrebujemo sezname,
ki so urejeni
Nobenih dodatnih lastnosti
Dodatne metode
SPREMENJENE metode
32