Öröklődés Polimorfizmus Csomagok Absztrakt osztályok, interfészek 5. gyakorlat Öröklődés Polimorfizmus Csomagok Absztrakt osztályok, interfészek
Objektumorientáltság, OO paradigma egységbezárás és információ elrejtése (absztrakt adattípus) adatok és a rajtuk végzett műveletek egységbezárása osztályok írása öröklődés polimorfizmus (többalakúság)
Öröklődés lényege: hasonló osztályokat ne kelljen újra létrehozni, hanem a már meglévő osztályt „klónozni”, majd módosítani (interfész újrafelhasználása) adattagok esetén: újak hozzáadása (a régiek is megmaradnak) metódusok esetén: újak hozzáadása meglevők felülírása (overriding)
Overriding és overloading közti különbség meglevő metódus a gyerekosztályban felülíródik azonos a név és a paraméterlista egy osztályon belül vannak a metódusok a metódusok neve ugyanaz, de a paraméterlistáik különbözők Overriding (felüldefiniálás) Overloading
Polimorfizmus (többalakúság) a fordítóprogram nem tudja, melyik konkrét operáció hívódik (örökölt vagy felüldefiniált)! futás közben derül ki a konkrét típus alapján kései kötés: Java-ban minden metódushívás ilyen az objektumokat őstípus alapján kezeljük minden gyerek ős típusú is egyben, de visszafelé ez már nem igaz! az ősosztály típusú objektumot váró metódus gyerekosztály típusút is kaphat
Polimorfizmus előnye: a kód nem függ a specifikus típusoktól utólag is lehet definiálni származtatottakat
Példa a polimorfizmusra
Példa a polimorfizmusra
Öröklődés Java: extends kulcsszó class SzármaztatottOsztály extends Ősosztály { // … } az ősosztálytól örökölt privát adattagok részei lesznek a származtatott osztálynak, de csak a publikus getter/setter metódusokkal tudjuk őket elérni konstruktorból az ősosztály konstruktorának hívásával: super kulcsszó
A this és a super kulcsszavak this: hivatkozás az aktuális objektumra super: hivatkozás az ősre Pl.: this hivatkozás az aktuális objektum egy konstruktorára hivatkozás az aktuális objektumra kiíratáskor super hivatkozás az ősosztály konstruktorára hivatkozás az ősosztály valamely metódusára
Példa öröklődésre Ősosztály: public class Allat{ private String fajnev; private int varhatoElettartam; public Allat(String fajnev, int vElettartam){ this.fajnev = fajnev; this.varhatoElettartam = vElettartam; }
Példa öröklődésre Gyerekosztály: public class Hal extends Allat{ A hal a fajnév és a várható élettartam mellett egy uszonyhossz adattaggal is rendelkezik. Gyerekosztály: public class Hal extends Allat{ private int uszonyhossz; public Hal(String f, int v, int u){ super(f, v); uszonyhossz = u; } Először az ősosztály konstruktorát hívjuk... …ezután inicializáljuk a hal osztályban deklarált új mezőket.
A toString() metódus Java-ban minden osztály (a beépítettek és az általunk írtak is) implicit módon (automatikusan) az Object nevű beépített ősosztálytól származik az Object biztosít néhány hasznos metódust, melyeket a származtatott osztályok felüldefiniálhatnak (method overriding) ezek közé tartozik a toString() metódus is
A toString() metódus toString() lényege: amikor kiíratunk egy objektumot, akkor az milyen formában íródjon ki ezt írhatjuk elő a toString() metódusban Pl.: public class Pont { private int x; private int y; public String toString() { return “x = ” + x + “, y = ” + y; }
A toString() használata ha ezután létrehozunk egy Pont típusú objektumot, és kiíratjuk azt: Pont p = new Pont(); System.out.println(p); …akkor valójában a toString() metódus fog meghívódni (automatikusan) és az általa visszaadott érték (String) kerül kiíratásra: x = 0, y = 0
Példaprogram Superman.java (pub) SMMain.java (pub)
Csomagok (packages) az osztályokat szokás csomagokba rendezni, csoportosítani valamilyen szempont alapján a forráskódban azt, hogy az adott osztály melyik csomagba tartozik, a következő módon jelöljük: package csomagnév; ennek az első nemkomment sorban kell lennie! Pl.: package hu.akarmi.www; („fordított domain”- szerű elnevezés) ha egy osztályt nem teszünk csomagba, akkor alapértelmezetten egy ún. default package-be kerül
Csomagok (packages) egy adott csomagban lévő osztály használata: import csomagnév.OsztályNév; egy adott csomagban lévő összes osztály használata: import csomagnév.*; példák: import java.util.ArrayList; import java.util.*;
Példa saját csomagra az Ember osztály használata: package myPackage; public class Ember { // … } az Ember osztály használata: myPackage.Ember e1 = new myPackage.Ember(); VAGY: import myPackage.*; ... Ember e1 = new Ember();
Automatikusan importálódó csomagok egyes csomagok osztályai automatikusan importálódnak a programunkba, anélkül hogy kérnénk az importálásukat ilyen a java.lang csomag összes osztálya a java.lang csomagban van például a Math osztály is, így ha beépített matematikai függvényeket szeretnénk használni, minden további nélkül használhatjuk a Math osztályt (semmit nem kell importálni)
Csomagok elnevezése a csomagnévbe a teljes elérési útvonal bele van kódolva a csomagokat a domain name alapján kell elnevezni, mégpedig annak megfordításából képezzük a csomag nevét: Pl. inf.u-szeged.hu hu.u_szeged.inf.Ember ennek megfelelő könyvtárszerkezetet is ki kell alakítani: hu könyvtár, azon belül u_szeged könyvtár, abban inf könyvtár, abban Ember.java
Névütközések ha két csomagunk is van ugyanolyan nevű osztállyal, és mindkettőt használni szeretnénk (amíg nem használunk ilyet, addig nincs baj) explicite ki kell írni a csomag nevét az osztály elé Pl. myPackage.Ember e1 = new myPackage.Ember(); myOtherPackage.Ember e2 = new myOtherPackage.Ember();
Statikus import import static csomagnév; az összes osztály adattagjait elérhetem az osztálynév nélkül Pl. a Math.PI helyett PI (java.lang)
Csomagok Eclipse-ben az Eclipse automatikusan elkészíti a könyvtárstruktúrát, amint létrehozunk egy ilyen nevű csomagot egyébként nekünk kell gondoskodni a megfelelő könyvtárak létrehozásáról! amit nem teszünk csomagba, az a default package-be kerül
Fordítás a csomagban levő legfelső könyvtár felett kell fordítani pl. javac hu\u_szeged\inf\Program.java Futtatás pl. java hu.u_szeged.inf.Program
Példaprogramok a pubban hu.u_szeged.inf.Seged.java hu.u_szeged.inf.TombMaximum.java DoubleTombMax1.java DoubleTombMax2.java hu.u_szeged.inf.DoubleTombMax3.java
Gyakorló feladatok pub: 5. gyakorlathoz tartozó feladat.txt
Absztrakt osztályok, interfészek
Absztrakt osztály nem példányosítható (fordítási hiba, ha megpróbáljuk a példányosítást) általánosítás: közös interfészt biztosít a leszármazottaknak abstract class Hangszer{ … }
Absztrakt metódus csak deklarációja van, definíciója (törzse) nincs leszármazott osztályokban fogjuk majd megvalósítani pl.: abstract public void szolj(Hang); ha egy osztálynak van legalább egy absztrakt metódusa, akkor az osztály is absztrakt absztrakt metódus nem lehet private és final, hiszen úgy nem lenne értelme (nem lehetne megvalósítani/felüldefiniálni)
Interfész az interfész olyan osztály, amiben csak absztrakt metódus van csak egy formát ad, implementáció nélkül interface Hangszer{ … }
Interfész metódusai: impliciten public és abstract mindegyik ahogy absztrakt osztálynál sem, úgy itt sem lehet private és final implements kulcsszóval lehet „származtatni” (implementálni) belőle több interfészt is implementálhatunk („többszörös öröklődés”, de nem igazi)
Interfész public class Zongora implements Hangszer{ … } public abstract class AlkoholosItal extends Ital implements Alkoholos{
Interfész interfészek is származhatnak egymásból 1 interfésznek lehet több ősinterfésze Az öröklődési hierarchiában nincsen minden interfésznek egy közös ősinterfésze (mint az Object az osztályoknál)
Instanceof vizsgáljuk meg, hogy egy objektumpéldány az adott osztályba tartozik-e instanceof kulcsszó public void kutyaE(Object o){ if (o instanceof Kutya){ System.out.println(”Ez egy kutya.”); } else{ System.out.println(”Ez nem egy kutya.”); }
Példaprogramok: italos feladat pub könyvtár 7. gyakorlat „alk” csomagban levő osztályok Absztinens és Iszakos csomagon kívüli osztályok
Példaprogramok: függvényes feladat pub könyvtár 7. gyakorlat „fgv” csomagban levő osztályok FuggvMain.java
Szorgalmi feladat szerda éjfélig küldhető el 3 pluszpontért nekem e-mailben Feladat: Írj egy Dolgozó osztályt: ez a következő protected láthatóságú adattagokkal rendelkezik: adószám, név, születési dátum (Date típusú), fizetés. Írj az osztályhoz paraméteres konstruktort, definiáld felül a toString metódust, valamint az adattagokhoz legyenek getter-setter metódusok! Írj az osztályhoz egy fizetésemelés metódust, mely egy számot vár paraméterül, és annyi százalákkal emeli meg a dolgozó fizetését.
Szorgalmi feladat Írj egy Főnök osztályt: ez a Dolgozóból származik, és azon felül a „vezetői szint” (értéke: projektmenedzser csoportvezetőosztályvezető vezérigazgató) és a „prémium” (egész szám, a fizetésen felüli prémium összege) privát adattagokkal rendelkezik. Ennek az osztálynak is legyen paraméteres konstruktora, getter-setter metódusai, toString metódusa felüldefiniálva. Definiáld felül a Főnök osztályban a Dolgozó fizetésemelés metódusát, a változás annyi, hogy a főnöknél a fizetés és a prémium is adott százalékkal emelkedik. Írj egy „előléptetés” metódust a Főnök osztályhoz, mely a következő vezetői szintre lépteti az adott egyedet. De csoportvezetői szintnél magasabbra a metódus nem léptethet senkit. A metódus igaz vagy hamis értékkel tér vissza attól függően, sikerült-e az előléptetés.
Szorgalmi feladat Írj egy futtatható osztályt: Hozz létre egy-két példányt a Dolgozó és a Főnök osztályokból, próbáld ki a metódusaikat. Mindhárom osztályt helyezd a „szorgalmi3” nevű csomagba!