Objektorienteeritud programmeerimine

**Objektorienteeritud programmeerimine** (OOP) on programmeerimise paradigma, mis kasutab "objekte" – andmestruktuure, mis koosnevad andmeväljadest ning meetoditest. Kasutusel võivad olla selliseid võtted nagu andmete abstraktsioon, kapseldamine, modulaarsus, polümorfism ning pärimine. Kuni 1990. aastateni polnud objektorienteeritud programmeerimine tarkvaraarenduses kuigivõrd levinud, kuid tänapäeval on selle tugi juba paljudesse programmeerimiskeeltesse sisse ehitatud.

## Ülevaade

Objekt on kindel hulk meetodeid, mis on seotud mingi kindla pärismaailma või abstraktse olemiga, näiteks pangakonto omaniku või tegelasega arvutimängus. Teised tarkvara osad saavad objektiga suhelda ainult tema avalikke meetodeid välja kutsudes. Suur hulk tarkvarainsenere leiab, et objektide sel viisil isoleerimine teeb tarkvara lihtsamini hooldatavaks ja jälgitavaks. Siiski leidub neid, kes tunnetavad vastupidist: tarkvara muutub keerulisemalt haldatavaks ning dokumenteeritavaks või üleüldse keerulisemaks kavandada.   

Objektorienteeritud programmeerimine sai alguse juba 1960. aastatel. Riist- ja tarkvara muutus aina keerulisemaks ning haldamine tõi tihti kaasa probleeme. Teadlased uurisid viise, kuidas säilitada tarkvara kvaliteeti ning tulemusena lõid objektorienteeritud programmeerimise, et vähendada tüüpilisi probleeme: rõhutati eraldiseisvate, taaskasutatavate programmiloogika osade kasutamist. Tehnoloogia keskendub andmetele, mitte protsessidele. Programmid koosnevad omaette moodulitest (klass), mille iga eksemplar (objekt) sisaldab kogu toimimiseks vajalikku informatsiooni. See on vastupidine juba olemasolevale modulaarsele programmeerimisele, mis keskendub funktsioonidele, mitte andmetele, kuid pakub võrdväärselt koodi taaskasutusvõimalusi. See tavapärasem lähenemine, mis siiani on püsinud, käsitleb andmeid ja käitumist eraldi.
  
Objektorienteeritud programmi võib seega vaadelda kui kogumit omavahel suhtlevaid objekte, erinevalt tavapärasest mudelist, kus programmi võib vaadelda kui nimekirja täidetavatest ülesannetest. Objektorienteeritud programmeerimises on iga objekt võimeline vastu võtma teateid, andmeid töötlema ja saatma teateid teistele objektidele ning on seetõttu vaadeldav kui iseseisev "masin", millel on kindel ülesanne programmi töös. 

Programmeerimiskeel Simula oli esimene, mis võttis kasutusele objektorienteeritud programmeerimise aluseks olevaid põhimõtteid, olles ALGOL-i täienduseks. Simula kasutas ka automaatset prahikoristust, mis oli varem välja mõeldud funktsionaalsele programmeerimiskeelele Lisp. Smalltalk oli esimene programmeerimiskeel, mida hakati nimetama objektorienteeritud keeleks.

## Põhilised ideed
### Klass

Klass defineerib olemi (objekti) abstraktsed omadused, muuhulgas ka olemi iseloomustavad omadused ning olemi käitumise ja oskused. Klass on nagu šabloon, mis kirjeldab millegi olemust. Näiteks klass **Koer** koosneks kõigile koertele omastest omadustest nagu näiteks tõug ja kasuka värv ning oskustest nagu haukumine ja istumine. Objektorienteeritud programmis on klassid need, mis pakuvad modulaarsust ning struktuuri.  

### Objekt
Objekt on klassi eksemplar.

### Eksemplar
Klassist saab luua eksemplari. Eksemplar on tegelik objekt, mis tekitatakse programmi täitmisajal. Objekt *Pauka* on klassi **Koer** eksemplar. Objekti olekuks nimetatakse tema atribuutide väärtust. Objekt koosneb olekust ning käitumisviisidest, mis on defineeritud selle objekti klassis. 

### Meetod

Meetod on objekti võime midagi teha. Meetodeid märgitakse tegusõnaga. *Pauka* on **Koer**, seega on tal võime haukuda. Seega `haugu()` on üks *Pauka* meetoditest. Tal võib olla ka teisi meetodeid, näiteks `istu()`, `söö()` või `kõnni()`. Meetod mõjutab tavaliselt ainult ühte kindlat objekti. Kõik **Koer** tüüpi objektid suudavad haukuda, kuid on vaja panna üks kindel koer haukuma.  

### Pärimine
Alamklassid on klassi kitsam versioon, mis pärib omadused ja käitumise oma ülemklassilt ning võivad lisada enda omi. 
Näiteks klass **Koer** võib omada alamklasse **Terjer**, **Taks** ning **Hurt**. Pauka võiks ka olla klassi **Koer** alamklassi **Hurt** eksemplar. Oletame, et klass **Koer** defineerib meetodi `haugu()` ning omaduse `kasukaVärv`. Iga selle alamklass pärib need liikmed ehk kood tuleb kirjutada ainult üks kord. Iga alamklass saab ka muuta oma päritud omadusi, näiteks vaikimisi oleks `kasukaVärv` **Taks** tüüpi objektidel pruunikas.

Pärimine on "x on y" seose tüüp. **Hurt** on **Koer**, Pauka on **Hurt**. Seega omab objekt Pauka omadusi nii klassist **Hurt** kui ka klassist **Koer**. 

### Abstraktsioon
Abstraktsioon on keerulise reaalse probleemi lihtsustamine modelleerides probleemile vastavaid klasse ning probleemile vastaval pärimisastmel.

Näiteks võib Paukat, kes on **Koer**, käsitleda kui **Koer** tüüpi objekti suurem osa ajast, **Hurt** tüüpi objekti, kui on vaja ligi pääseda tema hurdalikele omadustele ja käitumisele ning **Loom** tüüpi objekti (**Koer** ülemklass), kui Juku tahab kokku lugeda, kui palju on tal lemmikloomi.

Abstraktsiooni saavutatakse ka kompositsiooni abil. Näiteks klass **Auto** sisaldab **Mootor**, **Käigukast**, **Roolisüsteem** ja palju muid tüüpi objekte. Klassi **Auto** loomiseks ei ole vaja teada, kuidas erinevad komponendid sisemiselt töötavad, kuid on vaja teada, kuidas nendega suhelda (saata ja vastu võtta teateid).

### Kapseldamine
Kapseldamine eraldab klassi funktsionaalse sisu ja liidese. Meetodi `haugu()` sisu defineerib, kuidas haukumine toimub (`hingaSisse()`, `hingaVälja()`, `teeTeatudKõrgusegaHäält()`). Juku ei pea teadma, kuidas see kõik tegelikult toimub, talle on vaja teada, kuidas seda esile kutsuda. Kapseldamise saavutamiseks kirjeldatakse, millised klassid võivad objekti liikmeid kasutada. Tulemuseks on see, et objekt eksponeerib igale klassile kindla liidese - liikmed, mis on sellele klassile kättesaadavad. Eesmärgiks on see, et selle liidese kliendid ei sõltuks realisatsiooni nendest osadest, mis võivad tulevikus muutuda. Muudatuste tegemine muutub aga lihtsamaks.

### Polümorfism

Polümorfism võimaldab programmeerijal käsitleda päritud klassi eksemplare kui ülemklassi eksemplare. Polümorfism tähendab seda, et erinevat tüüpi objektid reageerivad sama nimega meetodi väljakutsetele, kuid käitumine sõltub objekti tüübist. Olgu meil klassid **Koer** ja **Siga**, mis on mõlemad päritud klassist **Loom**, mis sisaldab meetodit `ütleMidagi()`. Nii **Siga** kui ka **Koer** tüüpi objektid sisaldavad meetodit `ütleMidagi()`, kuid selle meetodi sisu on kahel erinev. Kui meil on **Koer** tüüpi objekt *koer* ja **Siga** tüüpi objekt *siga*, aga me käsitleme neid kui **Loom** tüüpi objekte, siis on mõlemad võimalik panna häälitsema, kasutades meetodit `ütleMidagi()`, objekti *koer* puhul aga kutsutakse objektisiseselt välja meetod `haugu()` ning objekti *siga* puhul meetod `röhitse()`.

## Vaata ka
*Klassipõhine objektorienteeritud programmeerimine

## Välislingid
* OOP põhimõtted (inglise keeles)
* OOP kasutus PHP's (inglise keeles)