Kihagyás

Objektumorientált programozás (OOP)

A Java objektumorientált programozási (OOP) nyelv, amely lehetővé teszi az osztályok és objektumok létrehozását. Az OOP alapelvei közé tartozik az öröklődés, a polimorfizmus, az absztrakció és az adat elrejtése. Az osztályok sablonként szolgálnak az objektumok létrehozásához, és tartalmazhatnak adattagokat (mezőket) és metódusokat (viselkedést). Az objektumok példányosítása után ezek a mezők és metódusok elérhetőek és használhatóak. Az OOP segítségével könnyen karbantartható, újrafelhasználható és skálázható kódokat hozhatunk létre.

Osztály létrehozása

Az osztályokat a class kulcsszóval hozhatjuk létre. Az osztály neve után kapcsos zárójelek között definiálhatjuk az osztály mezőit és metódusait. A láthatóságot (erről még később lesz szó) public-ra állítjuk, amelyet nem kötelező kiírni, mivel ez az alapértelmezett.

Szintaxis

  1. láthatóság (public, private, protected)
  2. class kulcsszó
  3. osztály neve
Szemely.java
1
2
3
public class Szemely {

}

Attribútumok megadása

Egy osztálynak vannak tulajdonságai (attribútumai). Jelen esetben egy személynek van neve, eletkor-a. Ezeket privát láthatóságúra kell beállítani, hogy csak ellenőrzött módon lehessen változtatni.

Szintaxis

  1. láthatóság (public, private, protected)
  2. típus (int, String, ...)
  3. változó neve
Szemely.java
1
2
3
4
public class Szemely {
    private String nev;
    private int eletkor;
}

Konstruktor

A konstruktor egy speciális metódus, amelyet az osztály példányosításakor hívunk meg. A konstruktorok neve megegyezik az osztály nevével, és nem rendelkeznek visszatérési értékkel. Láthatósága legtöbbször public, amelyet nem kötelező kiírni, hiszen ez az alapértelmezett.

Szemely.java
1
2
3
4
5
6
7
8
9
public class Szemely {
    private String nev;
    private int eletkor;

    public Szemely(String nev, int eletkor) {
        this.nev = nev;
        this.eletkor = eletkor;
    }
}

Alapértelmezett konstruktor

A Java nyelvben a Pythonnal ellentétben lehetőségünk van több konstruktor létrehozására. Ezek közül a leggyakoribb az alapértelmezett (default) konstruktor, amely nem vár paramétert. Ilyen esetben mi adjuk meg az alapértelmezett értékeket.

Szemely.java
public class Szemely {
    private String nev;
    private int eletkor;

    public Szemely(String nev, int eletkor) {
        this.nev = nev;
        this.eletkor = eletkor;
    }

    public Szemely() {
        this.nev = "John Doe";
        this.eletkor = 18;
    }
}
Main.java
1
2
3
4
5
6
7
public class Main {
    public static void main(String[] args) {
        Szemely valaki = new Szemely("Kis Pista", 25);

        Szemely noname = new Szemely(); // John Doe, 18
    }
}

Metódusok

Getter

A getter metódusok segítségével lekérdezhetjük az osztály attribútumait. Fontos, hogy a getter láthatósága legyen public, hogy bárki elérhesse.

Szemely.java
public class Szemely {
    private String nev;
    private int eletkor;

    public Szemely(String nev, int eletkor) {
        this.nev = nev;
        this.eletkor = eletkor;
    }

    public String getNev() {
        return nev;
    }
}

Setter

A setter metódusok segítségével módosíthatjuk az osztály attribútumait. A setter metódusok láthatóságát is public-ra kell állítani, hogy bárki elérhesse.

Szemely.java
public class Szemely {
    private String nev;
    private int eletkor;

    public Szemely(String nev, int eletkor) {
        this.nev = nev;
        this.eletkor = eletkor;
    }

    public String getNev() {
        return nev;
    }

    public void setNev(String nev) {
        this.nev = nev;
    }
}

toString

A toString metódus segítségével megadhatjuk, hogy az osztályunk példányai hogyan jelenjenek meg szöveges formában. Az alapértelmezett implementáció az objektum osztály nevét és az objektum memóriacímét adja vissza. A toString metódus láthatósága legtöbbször public, amelyet nem kötelező kiírni, hiszen ez az alapértelmezett.

Szemely.java
public class Szemely {
    private String nev;
    private int eletkor;

    public Szemely(String nev, int eletkor) {
        this.nev = nev;
        this.eletkor = eletkor;
    }

    @Override
    public String toString() {
        return "Szemely{" +
                "nev='" + nev + '\'' +
                ", eletkor=" + eletkor +
                '}';
    }
}

Most pedig használjuk fel a már korábban elkészített osztályunkat a Main osztályban.

Main.java
1
2
3
4
5
6
public class Main {
    public static void main(String[] args) {
        Szemely valaki = new Szemely("Kis Pista", 25);
        System.out.println("valaki = " + valaki); // ez meghívja a valaki.toString() metódust automatikusan
    }
}

Láthatóság

Mint a fenti példákban is láthattuk, több különböző láthatósági szabályt alkalmaztunk. Ez adja meg, hogy egy attribútumot, vagy metódust ki érhet el, használhat, módosíthat.

Láthatósági szabályok:

  • public: bárki elérheti
  • protected: az osztályon belül és az öröklődött osztályokban érhető el
  • package-private: az osztályon belül és a csomagon belül érhető el
  • private: csak az osztályon belül érhető el

Az alábbi táblázatban megtalálhatóak a különböző láthatósági szabályok összehasonlítása.

Method Class Package Subclasses World
public
protected
package-private
private

Abban az esetben, ha nem írunk láthatóságot, akkor az alapértelmezett láthatóság lesz érvényben, amely a package-private.

Így használd

Íratlan szabályként elmondhatjuk, hogy legtöbbször a Java nyelvben az attribútumok privátok, a metódusok pedig publikusak. Természetesen akadnak kivételek, de ezeket speciális esetben használjuk.

Osztály példányosítása

Az előzőekben megnéztük, hogy hogyan tudunk létrehozni osztályokat. Ezeket példányosítással tudjuk felhasználni. A változó típusa mindig az osztály neve lesz, amit követ a new operátor, hogy meghívjuk a konstruktort.

Szemely.java
public class Szemely {
    private String nev;
    private int eletkor;

    public Szemely(String nev, int eletkor) {
        this.nev = nev;
        this.eletkor = eletkor;
    }

    public String getNev() {
        return nev;
    }

    public void setNev(String nev) {
        this.nev = nev;
    }
}
Main.java
public class Main {
    public static void main(String[] args) {
        Szemely valaki = new Szemely("Kis Pista", 25);

        System.out.println(valaki.getNev());

        valaki.setNev("Nagy Pista");
        System.out.println(valaki.getNev());
    }
}

Öröklődés

Az öröklődés a Java nyelvben lehetővé teszi, hogy egy osztály örökölje egy másik osztály tulajdonságait és metódusait. Az öröklődés során az osztályok között egy hierarchia jön létre, amelyben az ősosztályt szülőnek, a leszármazott osztályt pedig gyereknek nevezzük.

Példaként vegyük a Jarmu osztályt, amelynek van egy loero, vegsebesseg és egy szin tulajdonsága, valamint egy dudal() metódusa. A Jarmu osztályból származtassunk egy Auto osztályt, amelynek van egy ajtokszama tulajdonsága, és amely felülírja a Jarmu osztály dudal() metódusát. Továbbá a Jarmu osztály leszármazottja a Motor osztály, amelynek van egy csomagtarto tulajdonsága, és amely szintén felülírja a Jarmu osztály dudal() metódusát.

A fenti szöveg elsőre kicsit átláthatatlannak tűnik, ezért alkalmazzunk olyan technikát, amivel tudjuk grafikusan is ábrázolni az osztályok közötti kapcsolatot. Erre szolgál az UML diagram.

UML diagram

Az UML diagramok segítségével ábrázolhatjuk az osztályok közötti kapcsolatokat. A fenti példában látható osztályok közötti kapcsolatot az alábbi diagrammal ábrázolhatjuk:

---
title: Öröklődés példa
---
classDiagram
    Jarmu <|-- Auto
    Jarmu <|-- Motor
    Jarmu : +int loero
    Jarmu : +int vegsebesseg
    Jarmu : +String szin
    Jarmu: +dudal()
    class Auto{
        +int kerekekszama
        +int ajtokszama
        +dudal()
    }
    class Motor{
        +boolean csomagtarto
        +dudal()
    }

Ősosztály

Az első lépés minden esetben az ősosztály elkészítése, amelyből majd származtatjuk a leszármazott osztályokat. A Jarmu osztályban definiáljuk azokat a tulajdonságokat és metódusokat, amelyeket a leszármazott osztályok is megörökölnek.

Láthatóság

Fontos, hogy az adattagok láthatósága protected legyen, különben nem lesznek elérhetőek az öröklődött osztályokban. A láthatóságon kívül más eltérés nincs az ősosztályban egy átlagos osztállyal szemben.

Jarmu.java
public class Jarmu {
    protected int loero;
    protected int vegsebesseg;
    protected String szin;

    public Jarmu(int loero, int vegsebesseg, String szin) {
        this.loero = loero;
        this.vegsebesseg = vegsebesseg;
        this.szin = szin;
    }

    public void dudal() {
        System.out.println("Pípí");
    }
}

Gyermek osztály

A Gyermek osztály esetében az extends kulcsszóval mondjuk meg, hogy melyik osztályból származtatjuk. Mindemellett a konstruktorban meghívjuk az ősosztály konstruktorát a super() metódussal. Itt már private láthatóságú adattagokat is definiálhatunk.

Auto.java
public class Auto extends Jarmu {
    private int kerekekszama;
    private int ajtokszama;

    public Auto(int loero, int vegsebesseg, String szin, int kerekekszama, int ajtokszama) {
        super(loero, vegsebesseg, szin); // Jarmu konstruktorának meghívása

        this.kerekekszama = kerekekszama;
        this.ajtokszama = ajtokszama;
    }

    public void dudal() {
        System.out.println("Tütü");
    }
}

Feladatok

Erdemjegy

Adatbeolvasás

Készítsünk egy csv fájlt, amelyben eltároljuk a jegyeinket az alábbi táblázatnak megfelelően:

Érték Adattípus Példa
Dátum String 2023-11-28
Jegy int 5
Típus String Témazáró
Súly int 1
Példa
jegyek.csv
1
2
3
2023-11-28,5,Témazáró,2
2023-10-15,3,Házi feladat,1
2023-09-30,4,Írásbeli dolgozat,1

A fenti példának megfelelően töltsük ki az eNapló szerint a jegyeinket.

Osztály létrehozása

Az elkészített csv fájl után hozzunk létre egy osztályt Erdemjegy néven, amelyben a későbbiekben el tudjuk tárolni a beolvasott adatokat.

---
title: Erdemjegy osztaly
---
classDiagram
    class Erdemjegy
    Erdemjegy : +String datum
    Erdemjegy : +int erdemjegy
    Erdemjegy : +String tipus
    Erdemjegy : +int suly
    Erdemjegy: +getErdemjegy()
    Erdemjegy: +getSuly()
Példa
Erdemjegy.java
public class Erdemjegy {
    private String datum;
    private int erdemjegy;
    private String tipus;
    private int suly;

    public Erdemjegy(String datum, int erdemjegy, String tipus, int suly) {
        this.datum = datum;
        this.erdemjegy = erdemjegy;
        this.tipus = tipus;
        this.suly = suly;
    }

    public int getErdemjegy() {
        return erdemjegy;
    }

    public int getSuly() {
        return suly;
    }
}

Javaslat

Ne hozzunk létre felesleges gettereket és settereket, csak azokat amelyekre szükségünk van! Így átláthatóbb lesz a kódunk és könnyebben megérthető.

Amennyiben elkészült az osztályunk, olvassuk be a fájl tartalmát és számítsuk ki a súlyozott átlag.

Fájl beolvasása

Első lépés a fájl beolvasása, amelyet már korábban láttunk.

Példa
Main.java
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        try {
            File textFile = new File("osztalyzatok.csv");
            Scanner scanner = new Scanner(textFile);

            while (scanner.hasNextLine()) {
                String sor = scanner.nextLine();
            }

            scanner.close();
        } catch (FileNotFoundException e) {
            System.out.println("error");
        }
    }
}

A csv fájl sorainak felbontása után hozzunk létre egy listát, amelyben tároljuk az osztályunk példányait, valamint daraboljuk fel a szöveget a , karaktereket mentén.

Példa
Main.java
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        ArrayList<Erdemjegy> jegyek = new ArrayList<>();

        try {
            File textFile = new File("osztalyzatok.csv");
            Scanner scanner = new Scanner(textFile);

            while (scanner.hasNextLine()) {
                String sor = scanner.nextLine();
                String[] oszlopok = sor.split(",");

                Erdemjegy jegy = new Erdemjegy(oszlopok[0], Integer.parseInt(oszlopok[1]), oszlopok[2], Integer.parseInt(oszlopok[3]));
                jegyek.add(jegy);
            }

            scanner.close();
        } catch (FileNotFoundException e) {
            System.out.println("error");
        }
    }
}

Miért kell a parseInt?

Az Integer.parseInt() metódus segítségével átalakítjuk a szöveges értéket számmá, hogy a későbbiekben tudjuk használni. Enélkül nem tudnánk semmilyen aritmetikai műveletet végezni az értékkel.

Súlyozott átlag kiszámítása

Végezetül pedig csak az átlagszámítás maradt hátra.

Emlékeztető

A súlyozott átlag kiszámításához minden egyes értéket meg kell szorozni a hozzá tartozó súllyal, majd ezeket az eredményeket össze kell adni, és az összeget el kell osztani a súlyok összegével. A súlyozott átlagot a következő képlettel számíthatjuk ki:

\[ \text{Súlyozott átlag} = \frac{\sum_{i=1}^{n} (x_i \cdot w_i)}{\sum_{i=1}^{n} w_i} \]

ahol:

  • \(x_i\) az \(i\)-edik érték,
  • \(w_i\) az \(i\)-edik érték súly,
  • és \(n\) az értékek számát jelöli.
Példa
Main.java
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        ArrayList<Erdemjegy> jegyek = new ArrayList<>();

        try {
            File textFile = new File("osztalyzatok.csv");
            Scanner scanner = new Scanner(textFile);

            while (scanner.hasNextLine()) {
                String sor = scanner.nextLine();
                String[] oszlopok = sor.split(",");

                Erdemjegy jegy = new Erdemjegy(oszlopok[0], Integer.parseInt(oszlopok[1]), oszlopok[2], Integer.parseInt(oszlopok[3]));
                jegyek.add(jegy);
            }

            scanner.close();
        } catch (FileNotFoundException e) {
            System.out.println("error");
        }

        double sum = 0;
        double db = 0;
        for (Erdemjegy jegy : jegyek) {
            sum += jegy.getErdemjegy() * jegy.getSuly();
            db += jegy.getSuly();
        }

        double atlag = sum / db;
        System.out.println("atlag = " + atlag);
    }
}