Objektid, klassid, pärimine
Vajadus objektorienteeritud lähenemise järele
1980-ndad aastad. Keerulised tarkvarasüsteemid.
Graafikakeskkonnad.
Suurte projektide
haldamine
- modulaarsus
- "kihilisus"
- toetus sõltumatute rühmade koostööks
- vigade võimalikult varajane avastamine
Taaskasutamine
(kasutada/muuta olemasolevat, mitte alustada nullist), keerukate
graafiliste kasutajaliideste programmeerimine
standardsemaks/lihtsamaks.
Objekti kõige üldisemas tähenduses kirjeldavad
- Olek
- Käitumine
- Identiteet
Kapseldus (ingl.k. encapsulation)
- Objekt (OOP mõttes) sisldab individuaalseid
andmeid (objekti olek) ning meetodeid
sedalaadi objektidega manipuleerimiseks (objekti käitumine).
- Objekti oleku kirjeldamisel
kasutatakse ka termineid atribuut - ingl.k. attribute,
omadus -ingl.k. property, (isendi)väli
- ingl.k. (instance) field, (isendi)muutuja
- ingl.k. (instance) variable, ... Olek ongi
määratud objekti (ehk isendi) atribuutide
väärtustega (vrd. kirje Pascalis, struktuur C-s).
- Objekti olekut ei saa muuta
suvaliselt, andmeid (olekut) ja lubatud operatsioone
(meetodeid) vaadeldakse ühtse tervikuna ("kapsel")
- iga objektide klassi jaoks on omad meetodid
selle klassi isenditega töötamiseks (vrd. abstraktsed
andmetüübid).
- Objekti andmeid muudetakse objekti
meetodite aktiviseerimise teel, aktiviseerimiseks
saadetakse objektile teade (ingl.k. message).
Teadete edastamise ja töötlemise mehhanismid on erinevates
süsteemides erinevad (vrd. funktsioonide väljakutsumine).
- Objekti käitumine ei pruugi
piirduda ainult selle objekti oleku muutmisega, see
kirjeldab ka suhtlemist teiste objektidega ning muid
reaktsioone/interaktsioone.
- Nii oleku kui ka käitumise juures
eristame avalikke (ingl.k. public) ning privaatseid
(ingl.k. private) aspekte - avalik liides on
"teistele kasutamiseks", privaatsed muutujad/meetodid on
realisatsiooni "eraasi" ja peidetud. Reeglina on
isendimuutujad privaatsed ja meetodid avalikud - nii on
tagatud andmete kaitse.
- Kaks erinevat objekti võivad
(juhuslikult) olla samas olekus - nende eristamiseks on
vajalik objekti identiteet (näit. osuti
[ingl.k. reference] konkreetses keskkonnas, mis on
igal objektil erinev).
Klass
- Reaalse maailma objektid on tugeva
identiteediga, nende klassifitseerimine on
abstraktsioon (näit. Miisu, "kass", "imetaja").
Objektorienteeritud lähenemisel me soovimegi võimalikult
kõrget abstraktsioonitaset - sel teel saab kirjutada
lihtsamaid/vähemvigaseid programme ja neid otstarbekalt
taaskasutada (ingl.k. reuse).
- Iga objekt kuulub mingisse klassi;
ta on selle klassi isend (ingl.k. instance),
vahel on kasutatud ka termineid eksemplar, esindaja (näit.
isend Miisu kuulub klassi "kass").
- Sama klassi isenditel on samad isendimuutujad(ingl.k.instance
variables) ja isendimeetodid (ingl.k. instance
methods), isendimuutujate väärtused (olek) on
üldjuhul erinevad (kui langevadki kokku, siis määrab
isendi tema identiteet).
- Klass võib sisaldada ka muutujaid ja
meetodeid, mis ei ole seotud isenditega, nn. klassimuutujad
(ingl.k. class variables, ka klassiväljad, ingl.k.
class fields, staatilised muutujad) ja klassimeetodid
(ingl.k. class methods, ka staatilised meetodid).
Klassimuutujad on ühised kõigile isenditele (tavaliselt
konstandid, näiteks kassi jalgade arv - 4) ja neid saab
kasutada nii klassimeetodites kui ka isendimeetodites.
Klassimeetodeid kasutatakse vahel uute isendite loomise
juures (isendiloome, ingl.k. instantiation),
samuti on neist abi siis, kui me ei soovi meetodit objekti
sisse kapseldada.
- Konstruktor on erikujuline
klassimeetod uute isendite loomiseks (new, malloc,
...), näiteks nn. "vabrik". Destruktor (free) isendite
hävitamiseks on vahel asendatud mälukoristusvahenditega
(ingl.k. garbage collection).
Pärimine (ingl.k. inheritance)
- Objektide omadusi saab kirjeldada
erinevatel tasemetel (näit. Miisu omadused, kasside
omadused, imetajate omadused, ...).
- Üldistamine (ingl.k. generalization)
lubab objektide sarnaseid omadusi kirjeldada kõrgemal
tasemel (näit. kehatemperatuur ei ole iseloomulik
atribuut ainult kassidele, vaid kõigile
imetajatele).
- Spetsialiseerimine (ingl.k. specialization)
on vastupidine protsess - me toome välja teatud
eriomadused, mida ei saa kirjeldada kõrgemal tasemel.
- Et saavutada minimaalset
andmete/programmide dubleerimist on vaja objekti iga
omadus realiseerida kõrgeimal võimalikul
abstraktsioonitasemel. Seega on vajalik objektide
hierarhiline struktuur, mida saab kirjeldada klasside ja
alamklasside abil. Alamklass (ingl.k. subclass)
e. tuletatud klass (ingl.k. derived class)
saadakse klassist spetsialiseerimise teel, ta pärib
(ingl.k. inherits) kõik oma vanema omadused (näit.
kasside klass pärib kõik imetajate klassi omadused ja
spetsialiseerib seda, lisades ainult kassidele
iseloomulikke omadusi). Antud klassi ülemklass
(ingl.k. superclass) on selle üldistus - tihti
jäetakse ülemklassis mingid atribuudid vaatluse alt välja.
- Atribuutide hulga seisukohalt vaadates
alamklass laiendab (ingl.k. extends) antud
klassi - lisanduvad mingid spetsiifilised atribuudid,
täpsustuvad kasutatavad meetodid (NB! Mitte segi
ajada - kass ei ole laiem mõiste kui imetaja, tal
on lihtsalt rohkem atribuute).
- Klass saab kirjeldada nn. abstraktseid
omadusi, mille sisu on kohustuslik määrata
alamklassides (üldjuhul siis igas alamklassis erinevalt,
aga sama nimega). Programmeerija saab neid abstraktseid
omadusi kasutada, aga programmi terviklik silumine pole
võimalik enne, kui kõik vajalikud abstraktsed omadused on
realiseeritud. Öeldakse ka, et klass delegeerib
(ingl.k. delegates) abstraktse omaduse määramise
alamklassidele (näit. geomeetrilise kujundi ekraanile
toomine). Sisuliselt on abstraktne omadus niisugune, mida
ei saa realiseerida ülemklassis - iga alamklass ise
peab sellega tegelema.
- Kui alamklass võib pärida mitme erineva
klassi omadused, siis on tegemist mitmese pärimisega
(ingl.k. multiple inheritance). Kui klasside
hierarhia on puu, siis on tegemist ühese pärimisega
(ingl.k. single inheritance). Mitmesest pärimisest
püütakse hoiduda, saab kasutada muid meetodeid.
Klass saab mõne
keele korral realiseerida erinevaid liideseid (interface) -
sisuliselt me asendame seose "A on erijuht B-st" seosega "A
oskab täita liidest B".
Teadete saatmine (ingl.k. message
passing), polümorfism
- Meetodite aktiviseerimiseks vahetavad
objektid teateid. Kui programmi kompileerimise ajal on
teada, milline teade millise meetodi aktiviseerib, siis on
tegemist varase seostamisega (ingl.k. early
binding). Varase seostamisega süsteeme ei loeta
praegu enam "tõeliselt" objektorienteerituteks. Kui teated
seotakse meetoditega programmi lahendamise ajal
(käitusaegne, ingl.k. runtime otsustus), siis on
tegemist hilise seostamisega (ingl.k. late
binding).
- Kui meetodis on tarvis väljendada teate
saatmist samale objektile, mille meetod see on, siis
kasutatakse objekti nimena spetsiaalset võtmesõna (this,
self, ...).
- Polümorfism võimaldab sama teate
erinevat interpreteerimist (s.t. meetodi valimist)
sõltuvalt klassist, millesse teate saaja kuulub.
Polümorfism võib olla kompileerimisaegne (üledefineerimine,
ingl.k. overloading) või käitusaegne (ülekate,
ingl.k. overriding). (Vrd. polümorfism
programmeerimiskeeltes).
- Ülekatet kasutatakse objektorienteeritud
raamistikus. Kui me soovime mingit meetodit
täpsustada/muuta, siis defineerime alamklassi ning selles
samanimelise meetodi, mis katab endise üle, s.t. alamklassi
kuuluva objekti korral rakendatakse teate saamisel uut
meetodit.
Näide
class Loom(object):
"""
Looma omadusi kirjeldav klass
"""
__nimi = '' # private
def vota_nimi(self):
return self.__nimi
def pane_nimi(self, nimi):
self.__nimi = nimi
def __init__(self, nimi):
self.pane_nimi(nimi)
@classmethod
def luua_nimeta(cls):
return cls('nimetu')
@classmethod
def luua(cls, nimi):
return cls(nimi)
def __del__(self):
print('Vabastati ' + self.vota_nimi())
def __str__(self):
return 'Olen loom ' + self.vota_nimi()
class Kass(Loom):
"""
Kassi omadusi kirjeldav klass.
"""
vurrupikkus = 0
def __str__(self):
return super().__str__() + ' ja sealjuures KASS'
class Koer(Loom):
"""
Koera omadusi kirjeldav klass.
"""
sabaga = True
def main():
"""
Main method.
"""
minu_kass = Kass.luua('Kiti')
minu_koer = Koer.luua_nimeta()
minu_loom = Loom.luua_nimeta()
minu_loom.pane_nimi('Patu')
print(minu_kass)
print(minu_koer)
print(minu_loom)
minu_loom = minu_koer
print(minu_loom)
minu_loom = minu_kass
print(minu_loom)
minu_kass = minu_loom
print(minu_kass)
Sama Javas
Sama Pascalis
Lihtne klass Pythonis
Pisut keerukam klass Pythonis
Mitmene pärimine
Jaanus Pöial