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 - Java objekti esindabki
tegelikult osuti).
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" (Javas Klass.getInstance()). Destruktor (free) isendite hävitamiseks
on vahel (näit. Javas) 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.
Javas on pärimine
ühene, aga on sisse toodud võimalus, et sama klass saab 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äit. lihtsa Java rakendi juures tuleb
paint-meetod üle katta Applet-alamklassis).
Näide
public class Loomad {
static public void main
(String[] argumendid) {
System.out.println ("Mida loomad ytlevad?");
Loom minuLoom
= new Loom ("Patu");
System.out.println (minuLoom); //kasutab toString() meetodit
Kass minuKass
= new Kass ("Kiti");
System.out.println (minuKass);
minuLoom =
minuKass;
System.out.println (minuLoom);
} //main lopp
} //Loomad lopp
class Loom {
private String nimi;
Loom (String s) {
//konstruktor
paneNimi (s);
}
public String votaNimi() {
return nimi;
}
public void paneNimi (String
s) {
nimi = s;
}
public String toString() {
//katame yle
return "Olen
loom " + votaNimi();
}
} // Loom lopp
class Kass extends Loom { //alamklass
private int vurrupikkus;
Kass (String s) {
super (s);
}
public String toString() {
//katame kaetu veel yle
return "Olen
KASS " + votaNimi();
}
} // Kass lopp
Vaatame veel näiteid:
Preili.java
Kellad.java
Arv.java
Jaanus Pöial