Liigu peamise sisu juurde

Klassid ja objektid

Õppevideo antud teemal:

Sissejuhatus

Klassid ja objektid on objektorienteeritud programmeerimises fundamentaalsed alustalad. Klass on mall või kavand mis määrab ära struktuuri ning käitumise. Objekt on sellest klassist loodud konkreetne eksemplar ehk kavandi tegelik teostus.

Vaadake klassi kui mõne maja ehitusplaani ning objekte kui maju, mis selle plaani järgi valmis ehitati. Ehitusplaan määrab ära, millised ruumid sellel majal peaksid olema, mis suuruses ning milliste omadustega. Valmis ehitatud majadel on need atribuudid olemas, kuid iga maja võib seest erinev olla.

Klass

Klass on programmeerija poolt loodud andmetüüp, mis toimib mallina seda tüüpi objektide loomiseks. Klass hoiab endas:

  • Väljasid (fields, atribuudid) ehk andmeid, mida klassiga seostatakse.
  • Meetodid ehk tegevused, mida klassist loodud objektidega saab teha.

Klass iseenesest ei tee midagi, teatud eranditega. Selleks, et klasse kasutada tuleb klassi põhjal luua objektid.

Klassi struktuur

Ütleme, et päris elus on meil olemas mingisuguse hoone joonis. Joonisel kujutatakse, milline hoone olema peab: milline on selle kuju, kui suur ta on jne. Koodis võib seda kirjeldada järgmiselt:

public class House {

// Fields
String color;
int sizeInSquareMeters;
String doorColor;

// Constructor method - what happens when we build the house
public House(String color, int sizeInSquareMeters, String doorColor) {
this.color = color;
this.sizeInSquareMeters = sizeInSquareMeters;
this.doorColor = doorColor;
}

// Methods
public void openFrontDoor() {
// ...
}
}

Antud klassis on:

  • Väljadeks color, sizeInSquareMeters ja doorColor - ehk milliste tunnuste järgi maju eristame.
  • Meetod openFrontDoor() - kuidas peaks käituma, kui on soovi esiuks lahti teha.

Selle joonise järgi saame majad valmis ehitada:

Objekt

Objekt on klassi konkreetne isend. Igal objektil on:

  • Oma koopia klassi väljadest (samade/erinevate väärtustega).
  • Ligipääs kasutada klassi meetodeid.

Objektide loomine

Objekte luuakse new märksõnaga. Tulles tagasi maja näite juurde, kui tahaksime House klassist nüüd maja luua, siis tuleks seda teha sedasi:

House myDreamHouse = new House("grey", 60, "blue");
  • House määrab ära muutuja tüübi.
  • myDreamHouse on muutuja nimi.
  • new annab märku, et tuleks luua uus objekt.
  • House() on klassi konstruktor, antud juhul koos argumentidega, mille põhjal nüüd objekt valmis ehitatakse.

Objektide kasutamine

Kui objekt on loodud, siis selle väljasid ja meetodeid saab kasutada punkt (.) operaatoriga:

House myDreamHouse = new House("grey", 60, "blue");

// Accessing object fields
System.out.println("House color: " + myDreamHouse.color);

// Accessing methods
myDreamHouse.openFrontDoor();
oht

NB! Selleks, et klassi välju või meetodeid kasutada, tuleb kõigepealt luua objekt. Klass ise ei sisalda andmeid ega täida meetodeid – see on ainult mall.

Kasutades klassi meetodeid ilma objekti luues tekib kompileerimisviga.

Selle jaoks on muidugi erand, mida tutvustatakse staatilisuse peatükis

Samuti on võimalik objekte kasutada ka ilma muutujasse salvestamata:

new House("white", 60, "black").openFrontDoor();

Seljuhul kasutatakse nn ajutist objekti. See lähenemine on kasulik olukordades, kus:

  • objekti on vaja kasutada ainult ühe korra
  • objekti olekut ei ole vaja hiljem uuesti kasutada
  • soovitakse kirjutada lühemat ja kompaktsemat koodi

Näiteks kui meetod täidab ühekordset tegevust (nt logimine, valideerimine, ühekordne arvutus), ei ole eraldi muutujat vaja. Samas selline lähenemine ei ole sobilik kõikjal, eriti tingimustes, kus korduvkasutus või objekti olek on tähtis.

Objektide iseseisvus

OOP üks põhilisi eeliseid on see, et ühest klassist on võimalik luua mitu objekti. Iga objekt on iseseisev ning vastutab enda sees olevate andmete eest ise.

Näiteks olgu meil loendur:

class Counter {
int count;

void increment() {
count++;
}

void display() {
System.out.println("Count: " + count);
}
}

Kui luua nüüd kaks loendurit ning neid erinevalt kasutada:

Counter counter1 = new Counter();
Counter counter2 = new Counter();

// Increment counter1 three times
counter1.increment();
counter1.increment();
counter1.increment();

// Increment counter2 once
counter2.increment();

Siis lõpptulemus oleks ka erinev:

counter1.display();  // Count: 3
counter2.display(); // Count: 1

Väljade vaikeväärtused

Tuletame meelde muutujate peatükki. Vaikimisi on objektide loomisel väljad automaatselt initsialiseeritud mingisuguse vaikeväärtusega.
Näiteks:

class Student {
String name;
int age;
double grade;
boolean active;

void displayInfo() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
System.out.println("Grade: " + grade);
System.out.println("Active: " + active);
}
}

class Main {
public static void main(String[] args) {
Student student = new Student();
student.displayInfo();
}
}

koodi väljund oleks:

Name: null
Age: 0
Grade: 0.0
Active: false

ehk objekt-tüüpi isendimuutujate vaikeväärtus on null, primitiivide puhul võrdväärsed vastendid (arv 0, 0.0, tõeväärtus false jne.).

Objektid mälus

Lisaks tuletame meelde ka andmetüüpide peatükki, täpsemalt mäluhalduse osa. Objekte hoitakse heap mälus ehk hoitakse viidet, kus see objekt mälus asub. Kui näiteks üritada objekte kloonida järgneval viisil:

class Person {
String name;
}

Person p1 = new Person();
p1.name = "Ago";

Person p2 = p1; // Copies reference, not the object itself
p2.name = "Taavi"; // As a result both p1 and p2 get the new name because the underlying object is the same

System.out.println(p1.name); // Taavi
System.out.println(p2.name); // Taavi

siis kopeeritakse viide objektile, mitte sisu. Tulemusena p2 muutmisel muutub ka p1.

null-väärtus

Samuti tasub meelde tuletada ka null-väärtuste eripära. Objekt-tüüpi muutujatele võib määrata ka null-väärtust, mis sisuliselt tähistab, et antud muutujal ei viita ühelegi väärtusele. Näiteks:

String name = null;         // OK
System.out.println(name); // null

int age = null; // Error

Lõpetuseks ka õppevideo sellest, kuidas klass ja objekt omavahel toimivad


Kuigi objektidel on vaikeväärtused, soovime sageli neid välju algväärtustega seadistada kohe objekti loomisel. Selleks kasutatakse konstruktoreid, mis võimaldavad määrata objekti väljade esialgsed väärtused ja teostada vajalikke algtegevusi.