Arvutiteaduse instituut
  1. Kursused
  2. 2024/25 kevad
  3. Objektorienteeritud programmeerimine (LTAT.03.003)
EN
Logi sisse

Objektorienteeritud programmeerimine 2024/25 kevad

  • Kodutööd ja praktikumid
  • Loengud
  • Kursuse korraldus
  • IDE juhend
  • Süvendusrühm
  • Silumisest

Lisamaterjalid 7

Lülitidirektiiv

Koodi kirjutades võib kujuneda olukord, kus tekib paljude harudega tingimusdirektiiv. Loetavuse parandamiseks saab seda mõnel juhul asendada lülitidirektiiviga, mida on tutvustatud esimeses praktikumis. Selles võrreldakse kindlat väärtust teiste väärtustega. Võrdväärse paari leidmisel minnakse vastavasse harusse.

Meetod hindeTähendus võtab argumendiks char-tüüpi muutuja hinne ja tagastab String-tüüpi muutuja tähendus kasutades tingimusdirektiivi. Kui hinne väärtus on 'A' või '5', siis tagastatakse sõne "suurepärane" ning nii 'F' või '0'-ni välja. (https://www.riigiteataja.ee/akt/122092021005 § 5. Hindamisskaalad). Vastasel juhul tagastatakse "sellist hinnet pole". Kuna A ja 5 tähendus on sama, saab luua kaks case-i nii, et ülemine haru jääb tühjaks. Sellisel juhul täidetakse mõlema haru sisu. Ülemisel harul võib siiski olla sisu, näiteks väärtuse 'C' korral väljastatakse sõne "C". Mitu erinevat võrreldavat väärtust saab komaga kokku panna üheks case-iks, nagu B ja 4.

public static String hindeTähendus(char hinne) {
    String tähendus;

    switch (hinne) {
        case 'A':
        case '5':
            tähendus = "suurepärane";
            break;
        case 'B', '4':
            tähendus = "väga hea";
            break;
        case 'C':
            System.out.println("C");
        case '3':
            tähendus = "hea";
            break;
        case 'D', '2':
            tähendus = "rahuldav";
            break;
        case 'E', '1':
            tähendus = "kasin";
            break;
        case 'F', '0':
            tähendus = "puudulik";
            break;
        default:
            tähendus = "sellist hinnet pole";
    }

    return tähendus;
}

Meetodi hindeTähendus tagastused:

hindeTähendus('A'); tagastab: suurepärane

hindeTähendus('5'); tagastab: suurepärane

hindeTähendus('C'); tagastab: hea ja väljastab: C

hindeTähendus('3'); tagastab: hea

Kuju case väärtus: asemel saab kasutada case väärtus ->. Sellega tekib vähem potentsiaalseid vigu, sest ei ole vaja kasutada võtmesõna break. Mitmerealise haru loomiseks kasutatakse looksulge { }.

public static String hindeTähendusLühem(char hinne) {
    String tähendus;

    switch (hinne) {
        case 'A', '5' -> tähendus = "suurepärane";
        case 'B', '4' -> tähendus = "väga hea";
        case 'C', '3' -> tähendus = "hea";
        case 'D', '2' -> tähendus = "rahuldav";
        case 'E', '1' -> tähendus = "kasin";
        case 'F', '0' -> tähendus = "puudulik";
        default       -> tähendus = "sellist hinnet pole";
    }

    return tähendus;
}

Meetod hindeTähendusLühem tegevuse näited:

hindeTähendusLühem('A'); tagastab: suurepärane

hindeTähendusLühem('5'); tagastab: suurepärane

hindeTähendusLühem('C'); tagastab: hea

Kuju case väärtus -> abil saab muutujaid kasutamata tagastada väärtusi:

public static String hindeTähendusLühemTagasta(char hinne) {
    return switch (hinne) {
        case 'A', '5' -> "suurepärane";
        case 'B', '4' -> "väga hea";
        case 'C', '3' -> "hea";
        case 'D', '2' -> "rahuldav";
        case 'E', '1' -> "kasin";
        case 'F', '0' -> "puudulik";
        default       -> "sellist hinnet pole";
    };
}

Meetod hindeTähendusLühemTagasta toimib samamoodi nagu hindeTähendusLühem:

hindeTähendusLühemTagasta('A'); tagastab: suurepärane

hindeTähendusLühemTagasta('5'); tagastab: suurepärane

hindeTähendusLühemTagasta('C'); tagastab: hea

Lülitidirektiivi väärtuse tagastamiseks saab kasutada ka võtmesõna yield. Seda kasutades peab katma kõik võimalikud olukorrad. Tavaliselt kasutatakse selle tingimuse täitmiseks võtmesõna default. Vastasel juhul tuleb kompileerides veateade.

public static String hindeTähendusYield(char hinne) {
    String tähendus = switch (hinne) {
        case 'A':
            yield "suurepärane";
        case 'B':
            yield "väga hea";
        case 'C':
            yield "hea";
        case 'D':
            yield "rahuldav";
        case 'E':
            yield "kasin";
        case 'F':
            yield "puudulik";
        default:
            yield "sellist hinnet pole";
    };

    return tähendus;
}

Võtmesõna yield kasutades:

hindeTähendusYield('A'); tagastab: suurepärane

hindeTähendusYield('C'); tagastab: hea

hindeTähendusYield('G'); tagastab: sellist hinnet pole

Enesekontroll

Instance of

Klassidega töötades võib tekkida vajadus kontrollida, kas muutuja on näiteks String või StringBuilder ning kas see üldse realiseerib liidest CharSequence. Selleks kasutatakse võtmesõna instanceof, mis tagastab tõeväärtuse sellest, kas mingi isend on kindel klass, selle alamklass või realiseerib konkreetset liidest.

Muutuja arv1 on klassi Integer isend:

Integer arv1 = 2;
System.out.println(arv1 instanceof Integer); // true

int-tüüpi muutuja arv2 ei ole Integer ja selle kontrollimine annab enne kompileerimist teate: Inconvertible types; cannot cast 'int' to 'java.lang.Integer', sest arv2 ei ole isend:

int arv2 = 5;
System.out.println(arv2 instanceof Integer);

Selle parandamiseks saab luua muutujast arv2 isendi:

System.out.println((Integer) arv2 instanceof Integer); // true

Muutuja võib olla lihtsalt Object:

Object arv3 = 8;
System.out.println(arv3 instanceof Integer); // true
System.out.println(arv3 instanceof String); // false

Muutuja list on klassi ArrayList, mis realiseerib liidest List, isend:

List<Integer> list = new ArrayList<>();
System.out.println(list instanceof List); // true
System.out.println(list instanceof ArrayList); // true

Klass LinkedList realiseerib liidest List, aga pole ArrayList-i ülemklass:

System.out.println(list instanceof LinkedList); // false

Meetod isendiTuvastamine võtab argumendiks objekti ja kontrollib, kas see on sõne, täisarv või tõeväärtus ning väljastab vastava sõnumi. Kui objekt on üks nendeks kolmest, salvestatakse see uute vastava tüübiga muutujasse, mida saab edasi kasutada täpselt nii nagu igat teist konkreetse klassi isendit:

public static void isendiTuvastamine(Object objekt) {
    if (objekt instanceof String sõne) {
        System.out.println("Isend on sõne: " + sõne);
    }
    else if (objekt instanceof Integer arv) {
        int arvKorda2 = arv * 2;
        System.out.println("Täisarvu " + arv + " kahega korrutamise tulemus on " + arvKorda2);
    }
    else if (objekt instanceof Boolean tõeväärtus) {
        if (tõeväärtus) System.out.println("Tõene");
        else System.out.println("Väär");
    }
    else {
        System.out.println("Pole ükski neist");
    }
}

Meetod isendiTuvastamineLüliti teeb sama, mida eelmine meetod, aga kasutab lülitidirektiivi. Mustrisobitamisel saab kasutada võtmesõna when, millega kontrollitakse lisatingimusi. Näiteks, kas muutuja sõne on tühi või tõeväärtus on tõene:

public static void isendiTuvastamineLüliti(Object objekt) {
    switch (objekt) {
        case String sõne when !sõne.isEmpty() -> System.out.println("Isend on sõne: " + sõne);
        case Integer arv -> System.out.println("Täisarvu " + arv +
                " kahega korrutamise tulemus on " + (arv * 2));
        case Boolean tõeväärtus when tõeväärtus -> System.out.println("Tõene");
        case Boolean tõeväärtus -> System.out.println("Väär");
        default -> System.out.println("Pole ükski neist");
    }
}

Mõlemad meetodid väljastavad sama tulemuse oletades, et sõne pole tühi. Siin on neist mõned näited:

int kuus = 6;
isendiTuvastamine(kuus);
isendiTuvastamineLüliti(kuus);

Väljastab kaks korda:

Täisarvu 6 kahega korrutamise tulemus on 12
String sõne = "Suur Tõll";
isendiTuvastamine(sõne);
isendiTuvastamineLüliti(sõne);

Väljastab kaks korda:

Isend on sõne: Suur Tõll
boolean tõene = true;
isendiTuvastamine(tõene);
isendiTuvastamineLüliti(tõene);

Väljastab kaks korda:

Tõene
char täht = 'e';
isendiTuvastamine(täht);
isendiTuvastamineLüliti(täht);

Väljastab kaks korda:

Pole ükski neist

Enesekontroll

Ehitusinstrumendid (build tools)

See nädal tutvusite teegiga JavaFX ja kasutasite sellega ehitusinstrumenti Maven. Ehitusinstrumendid loovad lähtekoodist käivitatavaid rakendusi ja automatiseerivad korduvaid tegevusi ning võivad korraldada teekide haldust. Javas on veel populaarsed Ant ja Gradle, mis on kõige uuem.

Gradle

Gradle kasutab projektide haldamiseks programmeerimiskeele Groovy või Kotlin baasil loodud faile. Need on tavaliselt vastavalt build.gradle või build.gradle.kts. Üldiselt on Gradle kiirem kui Maven ja Ant, eriti suurtes projektides. Seda osaliselt, sest ei tehta lisatööd, kui see pole vajalik. Näiteks, kui projekt on kompileeritud ja algfailide sisu ei ole muudetud, ei kompileerita koodi uuesti. Gradle’i hõlpsaks kasutamiseks eksisteerivad IntelliJ IDEA pistikprogrammid Gradle ja Gradle Extension.

JavaFX projekti loomine ja käivitamine

File → Project… → JavaFX → Build system: Gradle → JDK 21 → Next → Create

View → Tool Windows → Gradle

Avanenud menüüst: SinuProjektiNimi → Tasks → application → run

Java projekti loomine ja käivitamine

File → Project… → Java → Build system: Gradle → JDK 21 → ✓ Add sample code → Create

Täienda faili build.gradle lisades pistikprogrammidesse id 'application':

plugins {
    id 'java'
    id 'application'
}

ja application:

application {
    mainClass = 'org.example.Main
}

View → Tool Windows → Gradle Avanenud menüüst: SinuProjektiNimi → Tasks → application → run

Maven

Apache Maven kasutab projekti konfigureerimiseks märgistuskeelt XML. Sellega defineeritakse (tavaliselt failis pom.xml) projekti nimi, Java versioon, vajalikud pistikprogrammid, peaklass ning palju muud. See pole nii paindlik kui Gradle, kuid seevastu on väga standardiseeritud. Mavenis kasutatakse nii-öelda elutsükleid, mis hõlmavad näiteks kompileerimist, testimist ja pakendamist. IntelliJ IDEA kasutab Maveni integreerimiseks pistikprogramme Maven ja Maven Extension.

JavaFX projekti loomine ja käivitamine

File → Project… → JavaFX → Build system: Maven → JDK 21 → Next → Create

View → Tool Windows → Maven

Avanenud menüüst: SinuProjektiNimi → Plugins → javafx → javafx:run

Java projekti loomine ja käivitamine

File → Project… → Java → Build system: Maven → JDK 21 → ✓ Add sample code → Create

Lisa faili pom.xml uus pistikprogramm kompileeritud programmi käivitamiseks:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>3.5.0</version>
            <configuration>
                <mainClass>org.example.Main</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

Maveni kasutamiseks: View → Tool Windows → Maven

Avanenud menüüst:

SinuProjektiNimi → Lifecycle → compile

SinuProjektiNimi → Plugins → exec → exec:java

Ant

Apache Ant on neist kolmest kõige vanem ehitusinstrument tulles välja esimese versiooniga aastal 2000. Sarnaselt Maveniga kasutab Ant märgistuskeelt XML, aga sellel pole nii palju mugavusi ja on paindlikum. Lisaks projektide struktuuril on palju vähem piiranguid ja selle tõttu puudub standardsus. IntelliJ IDEA versioonist 2023.3 ja edasi pole pistikprogramm Ant automaatselt installitud. Selle paigaldamiseks: File → Settings → Plugins → Installi Ant.

Java projekti loomine ja käivitamine

File → Project… → Java → Build system: Intellij → JDK 21 → ✓ Add sample code → Create

Loo juurkausta fail build.xml sisuga:

<project>

    <target name="clean">
        <delete dir="build"/>
    </target>

    <target name="compile">
        <mkdir dir="build/classes"/>
        <javac srcdir="src" destdir="build/classes"/>
    </target>

    <target name="jar">
        <mkdir dir="build/jar"/>
        <jar destfile="build/jar/Main.jar" basedir="build/classes">
            <manifest>
                <attribute name="Main-Class" value="Main"/>
            </manifest>
        </jar>
    </target>

    <target name="run">
        <java jar="build/jar/Main.jar" fork="true" />
    </target>

</project>

Anti kasutamiseks: View → Tool Windows → Ant. Avanenud menüüst vajuta „Add Ant build file…“ peale ja vali just loodud fail. Teise variandina vajuta seonduva teavituse nupule „Add Ant build file“.

Töö nägemiseks mine Properties:

Eemalda linnukesed „Make build in background“ ja „Collapse finished targets in message view” eest:

Kompileerimiseks: compile

Pakendandamiseks: jar

Käivitamiseks: run

Kompileerimise ja pakendamisega tekkinud failide ning kaustade eemaldamiseks: clean

Enesekontroll

  • Arvutiteaduse instituut
  • Loodus- ja täppisteaduste valdkond
  • Tartu Ülikool
Tehniliste probleemide või küsimuste korral kirjuta:

Kursuse sisu ja korralduslike küsimustega pöörduge kursuse korraldajate poole.
Õppematerjalide varalised autoriõigused kuuluvad Tartu Ülikoolile. Õppematerjalide kasutamine on lubatud autoriõiguse seaduses ettenähtud teose vaba kasutamise eesmärkidel ja tingimustel. Õppematerjalide kasutamisel on kasutaja kohustatud viitama õppematerjalide autorile.
Õppematerjalide kasutamine muudel eesmärkidel on lubatud ainult Tartu Ülikooli eelneval kirjalikul nõusolekul.
Courses’i keskkonna kasutustingimused