Erinevus lehekülje "Java:Objektid" redaktsioonide vahel
164. rida: | 164. rida: | ||
// (Other instance variables have default initial values of zero.) | // (Other instance variables have default initial values of zero.) | ||
</source> | </source> | ||
+ | |||
+ | |||
+ | [[Category:Java Juhend|Objektid]] |
Redaktsioon: 10. märts 2015, kell 01:17
Objekt-orienteeritud programmeerimine (OOP)
Objekt-orienteeritud programmeerimine (ingl object oriented programming, OOP) on programmeerimise viis, kus programmi vaadatakse kui klasside/objektide kogumit. Java on suures osas objekt-orienteeritud programmeerimiskeel (primitiivsed andmetüübid (int, double jne) ei ole objektid).
OOP on tehnika, mis võimaldab programmeerimist mugavamaks teha. Eriti kasulik suurte projektide tükeldamisel. OOP ei tee lahendusi kiiremaks.
OOP peamised tehnikad/eesmärgid:
- informatsiooni kapseldamine (encapsulation). Teised programmeerijad ei saa kasutada osasid minu funktsioone ega muuta osasid minu muutujaid. Informatsioon peidetakse nende eest ära.
- Modulaarsus (modularity). Koodi jagamine mooduliteks. Seotud kapseldamisega, kus kapseldatud programm viiakse vastavusse pärismaailmaga.
- Polümorfism (polymorphism). Sama nimega meetod võib erinevate andmetüüpide puhul käituda erinevalt.
- Pärimine (inheritance). Pärinevussuhted klasside vahel, alamklassid pärivad kõik ülemklassi omadused ja meetodid, lisaks võib alamklass lisada funktsionaalsust.
- Koodi taaskasutamine. Kirjutada valmismooduleid, mida hiljem saab taaskasutada.
OOP põhikontseptsioon
Klassid on kui terviklikud tarkvara komponendid, mida saab kergesti (taas)kasutada. Keskne mõiste OOP juures on objekt, mis on justkui komponent, millel on andmed (olek) ja funktsionaalsus (käitumine).
Objekti oleku kirjeldamiseks kasutatakse ka järgmisi termineid: atribuut (attribute), omadus (property), (isendi)väli ((instance) field), (isendi)muutuja ((instance) variable).
Objekti andmeid muudetakse objekti meetodite abil. Meetodi aktiveerimiseks saadetakse objektile teade (message).
Näiteks elektronposti nimekirja objekt, millel olek (andmed) on kõik selle nimekirja nimed ja aadressid. Kui saata sellele objektile teade (kutsuda välja funktsiooni), mis lisab nime, muudetakse olekut vastavalt (lisatakse uus nimi). Kui saata sellele objektile teade (kutsuda välja funktsioon), mis prindib objekti välja, prindib objekt välja kõik nimed ja aadressid.
OOP ideoloogia
OOP tehnika tähendab mõnda konkreetset probleemi lahendavate objektide disainimist. Programmi objektid võivad esindada päriselu objekte antud probleemi puhul. Mida paremini (täpsemini, selgemini) päriselu objektid on programmi objektidena esitatud, seda lihtsam ja selgem on nendega opereerida. Näiteks kui programm peab lahendama ülesannet, mis on seotud sõiduki ja selle juhiga, siis on mõistlik luua programmi poolel objektid sõiduki ja juhi (inimese) kohta.
OOP võimaldab (suurema) programmi puhul:
- koodi paremini struktureerida
- hoida koodi arusaadavust lihtsana
- teha hiljem täiendusi koodi lihtsamini
jne.
Klassid ja objekt
Klass defineerib ära objekti abstraktsed omadused. Klass on nagu šabloon, mis kirjeldab millegi olemust. Näiteks klass Koer koosneks kõikide koerte omadustest nagu tõug ja värv ning oskustest nagu haukumine ja istumine. Objekt on konkreetne koer ehk isend. Klass Koer defineerib ära kõikide koerte omadused, objekt Lotte aga konkreetse isendi/koera, millele võib vastata (ei pea tingimata) reaalne koer. OOP puhul võib öelda, et klass on objektide kirjeldus, klass kirjeldab ära, milliseid andmeid/oskusi võivad sellesse klassi kuuluvad isendid (ehk objektid) omada.
Programmis on üldjuhul üks klass Koer, aga mitu erinevat objekti. Kui programm näiteks kirjeldab koerte varjupaiga andmeid, siis iga koera kohta varjupaigas on programmis üks objekt. Klass on aga neil kõikidel ühine.
OOP puhul öeldakse objekti kohta tihti isend (instance) või olem.
Java puhul:
- staatiline muutuja (
public static int dogCount;
) on klassi muutuja. Kuna klass ise kirjeldab ära kõik koerad, siis ka see muutuja käib kõikide koerte kohta. Selles võib näiteks hoida, mitu koera on varjupaigas. Kui kuskil seda numbrit muudetakse, muutub see üle kogu programmi. - mitte-staatiline muutuja (
String name;
), öeldakse ka objekti muutuja, isendimuutuja jne, kirjeldab ära ühe konkreetse objekti (koera) andmed, antud juhul koera nime. See võib olla kõikidel koertel erinev. Kui muudetakse ühe objekti nime, siis see ei muuda teiste koerte nimesid.
Klassi kirjeldus kirjeldab ära oskused, mida antud klassi isendid (objektid) teha oskavad. Neid oskusi nimetatakse meetoditeks (sisuliselt on need funktsioonid, aga objektide puhul räägitakse meetoditest). Objekti meetod võimaldab konkreetsel isendil mingit tegevust läbi viia. Näiteks koera puhul võib meetod olla haugu, mis siis paneb haukuma konkreetselt selle koera, kelle juures see meetod välja kutsuti (kellele saadeti vastav teade "haugu").
Java puhul:
- staatiline meetod e funktsioon (
public static int getDogLimit()
), nimetatakse ka klassi funktsiooniks või klassi meetodiks, on funktsioon, mis ei sõltu konkreetsest isendist. Näiteks see informatsioon, mis koera varjupaika mahub, ei sõltu ühestki konkreetsest koerast. See on kogu programmi kohta ühine funktsioon. - mitte-staatiline meetod (
public void bark()
), öeldakse ka isendimeetod, objektimeetod, on seotud aga konkreetse objektiga. Seda meetodit või funktsiooni rakendatakse ainult ühele konkreetsele isendile (loomulikult saab ka kõikidele rakendada, kui see iga objekti juures eraldi välja kutsuda).
Vaatame natuke teistsugust koodinäidet: <source lang="java">
/**
* Describes a student which * has some test results. * */
public class Student { /** * The name of the student. */ public String name; /** * Unique ID over all the students. */ public int ID; /** * The results of three tests. */ public double test1, test2, test3;
/** * Calculates the average test result. * @return Average test result */ public double getAverage() { return (test1 + test2 + test3) / 3; }
/** * Static variable which holds the next unique id. * The value of this variable is usually student count. * This is the same for all the students. */ private static int nextUniqueID = 0;
/** * Gets a unique ID for the student. * The ID number itself is increased. * @return Unique id for the student. */ public static int getUniqueID() { nextUniqueID++; return nextUniqueID; } }
</source>
Eelnevas õpilase näites on nii staatilisi kui mitte-staatilisi muutujaid/meetodeid. Staatiline getUniqueID()
ei sõltu otseselt ühestki tudengist. Ta sõltub vaid sellest, mis numbrid on juba määratud (unikaalne number eeldab, et ühelgi teisel tudengil sellist numbrit ei ole). Kõige lihtsam viis unikaalset numbrit saada on iga uue tudengi puhul anda ühe võrra suurem number kui eelmisele anti. Kui meil ülikoolis on 100 õpilast, siis me ei pea ühegi poole neist pöörduma, et saada uus unikaalne id. Seepärast ongi see meetod staatiline, kuna ta on kogu programmi (näiteks kogu ülikooli peale) ühine.
Meetod getAverage()
on aga seotud konkreetse tudengiga. Kui ülikoolist küsida "anna keskmine hinne", siis tähendaks see midagi muud. Kuigi jah, ülikooli näite puhul võib väita, et tegelikult ülikool teab ka kõikide tudengite keskmisi hindeid. Jah, teoreetiliselt võiks see meetod olla staatiline, aga siis oleks selle sisu hoopis teine. Antud näite puhul on aga eeldatud, et hinnete info on seotud konkreetse tudengiga. Kui nüüd ühelt konkreetselt tudengilt küsida, mis ta keskmine hinne on, siis ta saab sellele vastata (võtab lihtsalt aritmeetilise keskmise oma hinnetest).
Objektide loomine
Klassi nimi defineerib ära uue andmetüübi. Kõik senised objektid, mis te seni kasutanud olete (String, ArrayList jne) on tegelikult samamoodi kuskil ära kirjeldatud nagu meie Student objekt eelnevalt näidatud klassis.
Seega, klassinimi on kasutatav andmetüübina. Näiteks võime luua muutuja, mille andmetüüp on Student: <source lang="java"> Student std; </source>
Javas muutuja deklareerimine (nagu eelnevalt näidatud) ei loo veel objekti. Üldisemalt:
- Javas ükski muutuja ei salvesta endas objekti.
- Muutuja hoiab vaid viidet objektile.
Kui kujutada ette, et andmed paiknevad suvaliselt mälus laiali. Näiteks ühe tudengi andmed hakkavad positsioonilt 100, teise tudengi andmed hakkavad positsioonilt 1190 jne. Muutuja std ei hoia mitte tudengi andmeid endas, vaid hoopis viidet mällu. Seega, lihtsustatult võib öelda näiteks, et std = 100
(tegelikult viide objektile ei ole 1:1 mäluaadress, Javal on endal vahel mingi vastavustabel mäluaadresside jaoks).
Seega, Javas muutuja, mille andmetüüp on objekt (ükskõik kas teie enda loodud või mõni Java sisseehitatud objekt), salvestab vaid viite mällu. Viite (reference) või pointeri (pointer) täpset väärtust programmeerija teadma ei pea. Objekti loomisel teeb Java vajalikud protseduurid (eraldab objektile mälu ja määrab vastava aadressi muutujasse).
Objekti loomine toimub võtmesõnaga new: <source lang="java"> std = new Student(); </source>
Ülaltoodud kood loob uue objekti tüübiga Student
, salvestab selle mällu ja paneb vastava (alguse) mäluaadressi std
muutujasse. Loodud muutuja std
on kasutatav nüüd objektina. Selleks, et objekti muutujaid või meetodeid välja kutsuda, saab kasutada loodud muutujat, näiteks std.name
.
Nullviit
On võimalik, et muutuja nagu std
, millel on andmetüübiks klass, ei viitagi objektile. Sellisel juhul hoiab std
null-viita või tühja viita (null reference). Javas kirjutatakse null-viit null
. Muutujale saab null-viida omistada selliselt:
<source lang="java">
std = null;
</source>
ning null-viida testimine käib selliselt:
<source lang="java">
if (std == null) {
</source>
Kui muutuja väärtus on null
, siis isendi muutujate või meetodite poole pöördumine ei ole lubatud. Näiteks kui std = null;
, siis std.name
pöördumine pole lubatud. Kui seda tehakse, annab programm null pointer exception (NullPointerException) vea.
Instants
Konkreetset isendit või objekti nimetatakse instantsiks (instance). Järgnevalt näide, kuidas luuakse mõned instantsid eelnevalt näidatud Student
andmetüübiga.
<source lang="java"> // Declare four variables of type Student Student std, std1, std2, std3; // Create a new object belonging to the class Student, // store a ref to that object in the var std. std = new Student(); std1 = new Student(); // Create a second Student object std2 = std1; // Copy the reference value in std1 into the variable std2. std3 = null; // Store a null reference in the variable std3. std.name = "John Smith"; // Set values of some // instance vars, getUniqueIdisa static method, // therefore is accessed from class Student // (not object instance like std) std.ID = Student.getUniqueID(); std1.name = "Mary Jones"; std1.ID = Student.getUniqueID(); // (Other instance variables have default initial values of zero.) </source>