Programozás I. 5. gyakorlat 1
Objektumorientáltság Egységbezárás és információ elrejtése (absztrakt adattípus) Adatok és rajtuk végzett műveletek egységbezárása (osztályok írása, múlt hét) Öröklődés Polimorfizmus (többalakúság) 2
Öröklődés Lényege: hasonló osztályokat ne kelljen újra létrehozni, hanem a már meglévő osztályt módosítani Specializálás és általánosítás specializálás: őstől a gyerek felé (egyre speciálisabb osztályokat látunk) általánosítás: a gyerektől az ős felé (egyre általánosabb osztályokat láthatunk) 3
Öröklődés Adattagok: újakat hozhatunk létre (az örököltek is megmaradnak) Metódusok: újakat hozhatunk létre már meglévőket írhatunk felül (overriding) Java-ban csak egyszeres öröklődés van (azaz egy gyerekosztály csak egy ősből származik) 4
Overriding vs overloading Overriding: Már meglévő metódus felülírása egy gyerekosztályban Azonos név és paraméterlista Overloading: Egy osztályon belüli metódusok Egy metódusnév, de különböző paraméterlista 5
Öröklődés Java-ban az extends kulcsszóval class GyerekOsztá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, a super kulcsszóval 6
This/super this: hivatkozás az aktuális objektumra hivatkozás az aktuális objektum egy másik konstruktorára egy adattagjára kiíratáskor super: hivatkozás az ősre hivatkozás az ősosztály egy konstruktorára egy metódusára 7
Példa: Ősosztály public class Allat{ private String fajnev; private int varhatoelettartam; public Allat(String fajnev, int velettartam){ this.fajnev = fajnev; this.varhatoelettartam = velettartam; } } 8
Példa: Gyerekosztály public class Hal extends Allat{ private int uszonyhossz; public Hal(String f, int v, int u){ super(f, v); //Ős konstruktorának hívása uszonyhossz = u; } } A Hal rendelkezik az Állat összes adattagjával, valamint egy sajáttal (uszonyhossz) 9
Polimorfizmus (Többalakúság) Objektumok felcserélhetőségét biztosítja Fordításkor még nem tudjuk, hogy melyik konkrét operáció fog meghívódni (ö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 Objektumot az őstípusa alapján kezeljük Minden gyerektípus egyben őstípusú is Fordítva nem igaz! Őst váró metódus kaphat gyerek típust is 10
Polimorfizmus Előnyei: A kód nem függ a specifikus típusoktól Utólag is lehet definiálni származtatottakat Példakód: Test.java 11
Object (implicit öröklés) Java-ban minden osztály (a beépítettek és az általunk írtak is) implicit módon az Object nevű ősosztályból származik (közvetve vagy közvetlen) tehát az osztályhierarchia tetején mindig az Object áll az Object típusú változó bármilyen objektumra hivatkozhat ha egy metódus Object típusú paramétert vár, akkor annak bármilyen típusú objektumot átadhathatunk 12
A tostring() metódus Az Object osztály biztosít számunkra néhány hasznos metódust, melyet a származtatott osztályok felüldefiniálhatnak (de nem kötelező) pl.: clone(), equals(), hashcode(), finalize(), tostring, getclass(), notify(), notifyall(), wait() Egyik fontos ilyen metódus a tostring() A tostring() az objektumot Stringként reprezentálja Teszteléskor hasznos lehet 13
A tostring() használata Létrehozunk egy objektumot, majd ha kiíratjuk azt: Jarmu j = new Jarmu(); System.out.println(j); //Jarmu@58c9e870 Ilyen esetben valójában a tostring() metódus hívódik meg (automatikusan), amelyet ha nem definiálunk felül, akkor az Object-től örökölt tostring() kerül meghívásra Példakód: Superman.java, SMMain.java 14
Csomagok (packages) Az összetartozó (valamilyen szempont alapján) osztályokat csomagokba szokás szervezni A forráskódban azt, hogy egy adott osztály melyik csomagba tartozik az alábbi módon jelöljük: package csomagnév; A kódban az első nem komment sornak kell lennie! Egy osztálynak a teljes neve: packagenév.osztálynév (pl.: String java.lang.string) 15
Csomagok (packages) Csomag elnevezése: megállapodás által fordított domain elnevezés: pl.: hu.u_szeged.inf inf.u-szeged.hu Az ennek megfelelő mappaszerkezetről gondoskodni kell (hu/u_szeged/inf) Eclipse létrehozza, különben kézzel kell! Ha egy osztály nincs egyetlen csomagba sem, akkor alapértelmezetten egy default csomagba kerül 16
Csomagok (packages) Egy adott csomagban lévő osztály importálása: import csomagnév.osztálynév; Egy adott csomagban lévő összes osztály importálása: import csomagnév.*; Példa: import java.util.arraylist; import java.util.*; 17
Csomagok (packages) Egyes csomagok osztályai automatikusan importálódnak a programunkba, anélkül hogy ezt kérnénk Ilyen a java.lang összes osztálya, mint pl.: Wrapper osztályok Kivételek Math osztály, String, stb.. http://docs.oracle.com/javase/7/docs/api/java/lang/package-summary.html 18
Statikus import import static OsztályNév; Ezek után az osztály összes statikus adattagját elérhetjük, az osztálynév nélkül is: Pl.: a Math.PI helyett használhatjuk PI-t 19
Névütközések ha két csomagunk is van ugyanolyan nevű osztállyal, névütközés lehet ha 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é, amikor használjuk: mypackage.ember e1 = new mypackage.ember(); mynewpackage.ember e2 = new mynewpackage.ember(); 20
Absztrakt osztály Nem példányosítható (Ha megpróbáljuk, akkor fordítási hibát kapunk) Általánosítás: közös interfészt biztosít a leszármazottaknak abstract class Hangszer { }... 21
Absztrakt metódus Csak a deklarációja van, definíciója nincs (nincs függvénytörzs) leszármazott osztályokban kell megvalósítani pl.: abstract public void szolj(hang h); Ha van benne absztrakt metódus, akkor maga az osztály is absztraknak kell, hogy legyen absztrakt metódus nem lehet private és final, hiszen úgy nem lenne értelme (nem lehetne megvalósítani/felüldefiniálni) 22
Interfész Olyan osztály, amiben csak absztrakt metódus van Csak egy formát ad, implementáció nélkül Nincs benne az osztályhierarchiában interface Hangszer{... } 23
Interfész Metódusai: impliciten public és abstract nem lehet private és final implements kulcsszóval lehet interfészt implementálni több interfészt is implementálhatunk egyszerre 24
Interface vs. abstract class Interface: egyetlen metódust sem implementálhat implementáljuk több interface-t is implementálhatunk Abstract class: implementálhat metódusokat örököltetjük csak egyszeresen örököltethetünk 25
Interfész public class Zongora implements Hangszer{ }... public abstract class AlkoholosItal extends Ital implements Alkoholos{ }... 26
Instance of Ezzel vizsgálhatjuk meg az objektum típusát public void kutyae(object o){ if(o instanceof Kutya){ System.out.println("Ez egy kutya."); } else { System.out.println("Ez nem egy kutya."); } } 27
Feladatok Feladat (A megoldáshoz használjuk fel a PrivatEmber, Superman és SMMain osztályokat) Készíts egy abstract Ember osztályt. Vidd át a tostring metódust az Ember osztályba, majd módosítsd úgy a programot, hogy abstract legyen a tostring metódus. A PrivateEmber osztály öröklődjön az Ember osztályból. Probáld ki mit csinál az SMMain program, ha a tostring metódust kikommentezed! Definiálj egy Szuperkepessegek interfészt, amelynek van egy void kriptonittalsugároz() függvény osztályban, Implementáld ezt az interfészt a PrivatEmber osztályban, ahol nem csinál semmit (esetleg kiír valamit a konzolra), de definiáld felül a Superman osztályban úgy, hogy az csökkentse a szupererőt. (Az SMMain futtatóosztály is érdemes módosítani, hogy hívja ezt a függvényt valamilyen módon.) Helyezd csomagba a privatember és a Superman osztályokat. Az SMMain maradjon csomagon kívül.) 28