Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
B IT MAN89/1 v: 2018.03.13B IT MAN
5. Ea: OOP alapok
Java Programozás
Abstract Javaságok
B IT MAN89/2
B IT MAN89/3
OOP alapelvek
Adatok és a hozzájuk kapcsolódó tevékenységek egységbe zárása
(encapsulation)
– Alapegység: osztály, melynek építőkövei:
• adattagok,
• metódusok.
Információ rejtés: Egy objektum adatai a külvilág számára
hozzáférhetetlenek. Egy objektum a külvilággal csak az interfészén
keresztül tarthatja a kapcsolatot. (Interface: a külvilág számára
elérhető módszerek –metódusok– együttese.) A módszerek
implementációja rejtett.
Öröklődés (inheritance): az osztályok egy részét már meglévő
osztályok továbbfejlesztésével hozzuk létre, úgy, hogy további
adattagokkal, illetve metódusokkal bővítjük.
Többalakúság (polimorphism): A származtatott osztályokban
lehetnek ugyanolyan elnevezésű, de más tevékenységű metódusok,
mint az ős osztályban => áttekinthető kód, nem kell az
elnevezéseket variálnunk.
B IT MAN89/4
További OOP alapfogalmak
Osztály: Objektumok közös tulajdonságait definiálja.
Programozástechnika szempontból egy típus. Építőkövei:
– adattagok (attribútumok, jellemzők, tulajdonságok),
– metódusok (műveletek, viselkedés).
Objektum: Egy osztály egy működőképes példánya. Egy adott
osztályban definiált tulajdonságokkal tetszőleges számú
objektum példányosítható. Minden objektum természeténél
foga különbözik az összes többitől. Egy adott osztályból
példányosított valamennyi objektumnak ugyanolyan
lehetséges viselkedési módjai vannak, de mindnek saját
állapota van.
Üzenet: Az objektummal való kommunikáció módja. A
módszerek (metódusok) aktivizálását jelenti.
B IT MAN89/5
B IT MAN89/6
Öröklődés
Fogalma: új osztály létrehozása (gyermek) egy már
meglévő osztályt (szülő) felhasználva (kód
újrafelhasználás).
A gyermek osztály örökli a szülő osztály összes tagját, -
kivéve a konstruktorokat és az inicializáló blokkokat -,
definiálhat új tagokat és módosíthat örökölt tagokat.
B IT MAN89/7
Öröklődés
Gyakran előfordul, hogy egy program különböző
osztályai azonos adattagokkal és metódusokkal
rendelkeznek
Példa: Neptun felhasználók
B IT MAN89/8
Öröklődés
Az előző példában minden osztályban szerepel három
azonos adat:
– név, neptunKód, jelszó
Minden osztályban szerepel a:
– Bejelentkezés() metódus
Az osztályok ezen kívül rendelkeznek csak rájuk
jellemző adattagokkal és metódusokkal is
Az adattagok és metódusok ismétlődése problémákat
okozhat:
– pazarlás
– metódusoknál biztosítani kell az azonos működést
– a módosításokat több helyen át kell vezetni.
A megoldás: öröklődés
B IT MAN89/9
Öröklődés
A közös adatok és metódusok egy ős osztályba
gyűjthetők.
Ennek neve legyen NeptunFelhasznaló
Az egyes felhasználó osztályok ezek leszármazottjaiként
deklarálhatók.
A leszármazottak öröklik a közös tagokat.
Ezzel kód megosztás jön létre: a leszármazottak
használhatják a szülő osztály metódusait.
B IT MAN89/10
Öröklődés
Az öröklődés jele:
A nyíl a leszármazott osztály felől az ősosztály felé mutat
B IT MAN89/11
Öröklődés
Jellemzői:
– Egyszeres öröklés: egy gyermeknek csak egy szülője
lehet. (C++-ban többszörös)
– Egy szülőnek több gyermeke lehet
– Egy gyermek szintén lehet szülő
– Egyetlen korlátozás: egy osztály még közvetett módon
sem lehet saját maga őse
Elnevezések:
– Ősosztály, szülő (super class, base class)
– Leszármazott, gyermek (subclass, derivered class)
B IT MAN89/12
Öröklődés
Megadása:
– Ha nem adunk meg szülő osztályt, akkor automatikusan a
java.lang.Object osztály a szülő.
– Az Object tehát minden osztály őse, tagjait minden
osztály örökli!
– A gyermek osztály örökli szülője tagjait, de:
• a private tagokhoz nem fér hozzá,
• a félnyilvános tagokhoz pedig csak akkor, ha
ugyanabban a csomagban van (ezeket a szülő osztály
hozzáférhető tagjainak segítségével kezelheti)
• a protected, public tagokhoz közvetlenül hozzáfér.
class osztálynév extends ősosztály {
…
}
B IT MAN89/13
Konstruktorok az öröklődés során
A konstruktor nem öröklődik. Mind az ős osztály, mind a
leszármazott osztály rendelkezhet konstruktorral (akár többel
is). Egy leszármazott objektum példányosításánál tisztázni
kell:
– A konstruktorok végrehajtási sorrendjét
– Azt, hogy hogyan választhatjuk ki az ősosztály
konstruktorai közül a végrehajtandót
Végrehajtási sorrend: először mindig az ősosztály, majd a
leszármazott osztály konstruktora hajtódik végre. A pontos
sorrend:
– Az ős osztály adattagjainak inicializálása
– Az ős osztály konstruktorának végrehajtódása
– A gyermek osztály adattagjainak inicalizálása
– A gyermek osztály konstruktorának végrehajtódása
B IT MAN89/14
Konstruktorok az öröklődés során
Az ős osztály konstruktorának kijelölése:
– A gyermek osztály első sorában szerepelhet egy
super(paraméterek) konstruktorhívás. A paraméterlistának
az ős osztály valamelyik konstruktorára illeszkednie kell.
– Ha ilyen hívás nem szerepel a gyermek osztály
konstruktorában, akkor egy implicit super() hívással
kezdődik a konstruktor végrehajtása.
– Következmények:
• ha a gyermek osztálynak van olyan konstruktora,
amelyben nincs explicit ős konstruktor hívás, a szülő
osztálynak kell legyen paraméter nélküli konstruktora.
• Ha a gyermek osztálynak csak implicit konstruktora
van, az is az ős osztály paraméter nélküli konstruktorát
hívja meg.
B IT MAN89/15
public class Szemely {String nev;int kor;
public Szemely(String nev, int kor){this.nev = nev;this.kor = kor;
}public Szemely(){
this("Kis Béla", 25);}
}
public class Dolgozo extends Szemely {String munkakor;int fizetes;
public Dolgozo(String munkakor,int fizetes){super();this.munkakor = munkakor;this.fizetes = fizetes;
}}
Dolgozo d = new Dolgozo("tanár", 550);
1
2
3
4
B IT MAN89/16
public class Szemely {String nev;int kor;
}
public class Dolgozo extends Szemely {String munkakor;int fizetes;
public Dolgozo(String munkakor,int fizetes){this.munkakor = munkakor;this.fizetes = fizetes;
}}
Dolgozo d = new Dolgozo("tanár", 550);
1
2
Szemely(){
nev = null;
kor = 0;
}Szemely() ?? NO! 3
4
Konstruktorok az öröklődés során
B IT MAN89/17
public class Szemely {String nev;int kor;
public Szemely(String nev, int kor){this.nev = nev;this.kor = kor;
}} Szemely() ?? NO! 2
public class Dolgozo extends Szemely {String munkakor;int fizetes;
public Dolgozo(String munkakor,int fizetes){this.munkakor = munkakor;this.fizetes = fizetes;
}}
1
Konstruktorok az öröklődés során
B IT MAN89/18
public class Szemely {String nev;int kor;
{nev = "Kis Béla"; kor = 25;}public Szemely(String nev, int kor){
this.nev = nev;this.kor = kor;
}}
2
public class Dolgozo extends Szemely {String munkakor;int fizetes;
public Dolgozo(String munkakor,int fizetes){this.munkakor = munkakor;this.fizetes = fizetes;
}}
1
Konstruktorok az öröklődés során
1. Adattagok deklarálása
2. Inicializálás
3. Konstruktor végrehajtás
4. A változó referenciájának
beállítása
Szemely() ?? NO!
B IT MAN89/19
Öröklődés
Adattagok öröklése:
– A leszármazott örökli az összes adattagot, és új
adattagokat is definiálhat
– Definiálhat egy örökölt adattaggal megegyező nevű
adattagot is, ilyenkor az örökölt tagot elrejti (hide)
– Az elrejtett tagra a super kulcsszóval hivatkozhatunk:
• super.adattag
• super.super.adattag hívás nem lehetséges!
B IT MAN89/20
public class Szemely {String nev;int fizetes;
public Szemely(String nev, int fizetes){this.nev = nev;this.fizetes = fizetes;
}}
public class Dolgozo extends Szemely {int fizetes;
public Dolgozo(String nev, int fiz1, int fiz2){super(nev, fiz1);fizetes = fiz2;
}} public class OuterP {
public static void main(String args[]) {Dolgozo d = new Dolgozo("Béla", 550, 200);System.out.println(d.nev+" - "+d.fizetes);Szemely sz = d;System.out.println(sz.nev+" - "+sz.fizetes);
}}
Adattagok
öröklődéskor
B IT MAN89/21
public class Szemely {String nev;int fizetes;
public Szemely(String nev, int fizetes){this.nev = nev;this.fizetes = fizetes;
}}
public class Dolgozo extends Szemely {int fizetes;
public Dolgozo(String nev, int fiz1, int fiz2){super(nev, fiz1);fizetes = fiz2;
}public int getSzemFiz(){
return super.fizetes;}
} public static void main(String args[]) {Dolgozo d = new Dolgozo("Béla", 550, 200);System.out.println(d.nev+" - "+d.fizetes);System.out.println(d.getSzemFiz());
}
Adattagok
öröklődéskor
B IT MAN89/22
Öröklődés
Metódusok öröklése
– A leszármazott örökli az összes nem private metódust és
újakat is definiálhat, valamint megváltoztathat örökölt
metódust
– Esetek:
1. Új metódus: Az örökölt metódusoktól eltérő nevű
metódus definiálása
2. Új metódus örökölt metódus túlterhelésével
(overloading): az egyik örökölt metódussal
megegyezik a név, de eltér a paraméter szignatúra.
3. Példányszintű metódus felüldefiniálása (override): az
egyik örökölt példányszintű metódussal megegyezik a
szignatúra és a visszatérési érték típus
Paraméter szignatúra: A formális paraméterek száma és típus-sorrendje.
A visszatérési érték típusa ebből a szempontból közömbös.
B IT MAN89/23
Öröklődés
– Metódusok öröklése – Esetek (folytatás):
4. Örökölt metódus elrejtése új metódussal (hide): az
örökölt osztályszintű metódussal megegyező
szignatúra és visszatérési érték.
5. Hibás definiálás:
– Az örökölt metódustól gyengébb hatáskörű metódus
(private < félnyilvános < protected < public)
– Az örökölt metódussal azonos szignatúrájú de eltérő
visszatérési értékű metódus (hibás felüldefiniálás vagy
elrejtés)
– Az örökölt osztályszintű metódussal azonos szignatúrájú
példányszintű metódus
– Az örökölt példányszintű metódussal azonos
szignatúrájú osztályszintű metódus
– final módosítójú metódussal azonos szignatúrájú
metódus
B IT MAN89/24
Öröklődés
Egy osztályhoz több metódus is tartozhat azonos névvel, de
különböző paraméterszignatúrával.
A metódus hívásakor a fordítóprogram az aktuális
paraméterek szignatúrája alapján dönti el, hogy melyik
metódust kell alkalmaznia.
Ha egy megfelelőt sem talál, vagy ha többet is talál
hibajelzést ad.
Egy osztályhoz úgy tartozhat több azonos nevű metódus,
hogy:
– az osztályban definiálhatók azonos nevű metódusok
– ugyanilyen nevű metódusokat örökölhet is az osztály
A saját és örökölt metódusok együttesére érvényes az
overloading szabályrendszere
B IT MAN89/25
Metódusnév túlterhelés
public class Szemely {String név;int fizetés;
int getFizetés(){return fizetés;
}void fizetéstEmel(int fizetés){
this.fizetés += fizetés;}
}
public class Alkalmazott extends Szemely {String beosztás;
void fizetéstEmel(){fizetés += 20000;
}void fizetéstEmel(Alkalmazott a){
if (a.getFizetés() > fizetés) fizetés = a.getFizetés();
}}
Az Alkalmazott osztályban a fizetéstEmel metódus három különböző
paraméterszignatúrával is használható.
B IT MAN89/26
Metódusnév felüldefiniálás
public class Alkalmazott {String név;int nyelvekSzama;
public int potlek() {return nyelvekSzama*20000;
}}
public class Fonok extends Alkalmazott {int beosztottakSzama;
public int potlek() {return super.potlek() + beosztottakSzama*10000;
}}
Az ősosztály potlek() metódusának meghívása
B IT MAN89/27
Teszt 1.
Helyes vagy hibás az alábbi kód?
public class Komplex {
int x, y, z;
Komplex(int x, int y, int z){
this(x, y, z);
}
}
B IT MAN89/28
Teszt 2.
Az adatok láthatóságát szűkíthetjük
Az ősosztály adatait felüldefiniálhatjuk
Új metódusokat deklarálhatunk
Az ős osztály metódusait felüldefiniálhatjuk
Mire van lehetőségünk az utód osztályban egy
osztály örökítésekor?
B IT MAN89/29
Teszt 3.
Névegyezőség esetén egy konstruktorban milyen
minősítővel hivatkozhatunk az osztály adattagjaira?
this()
super.
super()
this.
B IT MAN89/30
Teszt 4.
Mi a konstruktor?
Osztályt definiáló metódus
Öröklődést beállító metódus
Objektumot létrehozó metódus
Példányosításkor meghívódó metódus
B IT MAN89/31
Teszt 5.
Milyen típusú konstruktor van az osztályban?
public class Alma {
String nev;
Alma (){
}
}
Implicit
Explicit
B IT MAN89/32
A kötés (binding) fogalma
A fordítóprogram elsődleges feladata, hogy az általunk
megírt forráskódot elolvassa, elemezze, megértse. Ezen
elemzés közben listát vezet a kód olvasása során
felismert változókról, konstansokról, típusokról,
függvényekről. Az egyes programozási elemekhez
rendelt nevek alapján képes felismerni melyik
programsorban melyik, korábban definiált elemre
hivatkozunk.
Kötés-nek nevezzük azt a folyamatot, amikor a
fordítóprogram a forráskód fordítása során felfedezett
metódushívásokhoz konkrét metódust rendel.
B IT MAN89/33
A kötés (binding) fogalma
A fordítóprogram elsődleges feladata, hogy az általunk
megírt forráskódot elolvassa, elemezze, megértse. Ezen
elemzés közben listát vezet a kód olvasása során
felismert változókról, konstansokról, típusokról,
függvényekről. Az egyes programozási elemekhez
rendelt nevek alapján képes felismerni melyik
programsorban melyik, korábban definiált elemre
hivatkozunk.
Kötés-nek nevezzük azt a folyamatot, amikor a
fordítóprogram a forráskód fordítása során felfedezett
metódushívásokhoz konkrét metódust rendel.
B IT MAN89/34
A kötés (binding) fogalma
A kötés típusai:
– Korai kötés: a fordítóprogram egy objektum statikus
típusa, vagy az aktuális paraméterek statikus típusa
alapján az azonosítást egyértelműen el tudja végezni.
• Egyedi metódusnevek
• Egy osztályon belül azonos nevű függvények, eltérő
paraméter szignatúrával.
– Késői kötés: a fordítóprogram az azonosítást nem tudja
elvégezni, a kötés csak futásidőben jöhet létre:
• Felüldefiniált metódusok, ahol metódus hívásánál dön-
teni kell, hogy az örökölt vagy a saját változat hívódjon
meg. A döntés alapja a hivatkozás dinamikus típusa.
• Mivel a dinamikus típus fordítási időben nem ismert, a
felüldefiniált metódusok közötti választást futásidőre
kell halasztani.
B IT MAN89/35
Statikus és dinamikus típus
Egy változónak van statikus és dinamikus típusa.
Egy változó statikus típusa az, amelyet a
deklarációjában megadtunk
– Ez a változó teljes élete alatt változatlan
– Ez határozza meg, hogy milyen műveleteket
végezhetünk a referenciával hivatkozott objektummal
Egy változó dinamikus típusa az általa éppen hivatkozott
objektum tényleges típusa.
– Csak olyan típus lehet, amely rendelkezik ugyanazokkal
az adatokkal és műveletekkel, mint a statikus típus, ezért a
változó dinamikus típusa csak a statikus típus vagy annak
leszármazottja lehet.
– A dinamikus típus a program futása során bármikor
változhat
B IT MAN89/36
Statikus és dinamikus típus
Egyszerű példa: miből mi lehet?
Gyümölcs a, b;
a = new Alma("Jonatán");
b = new Gyümölcs("Kiwi");
a = b;
a = new Körte("Vilmos");
Körte
Gyümölcs
Alma
Deklarálás
Statikus
értékadás
típus név érték
Gyümölcs a Alma Jonatán
Gyümölcs a
Példányosítás
Dinamikus
értékadás
Gyümölcs b
Gyümölcs b Gyümölcs Kiwi
Gyümölcs a Gyümölcs Kiwi
Értékadás
Dinamikus
értékváltás
Egy gyümölcs példány
lehet Gyümölcs, Alma,
vagy Körte típusú.
Alma példány csak
Alma típusú lehet.
Körte példány csak
Körte típusú lehet.Gyümölcs a Körte Vilmos
Újra
példányosítás
Dinamikus
értékadás
B IT MAN89/37
Statikus és dinamikus típus
Mi történik?
Gyümölcs a = new Körte("Vilmos");
Körte c = new Körte("Vilmos");
a = c;
c = a;
Körte
Gyümölcs
Alma
típus név érték
Körte c Körte Vilmos
Egy gyümölcs példány
lehet Gyümölcs, Alma,
vagy Körte típusú.
Alma példány csak
Alma típusú lehet.
Körte példány csak
Körte típusú lehet.
Gyümölcs a Körte Vilmos
A Gyümölcs típusú statikus változóba
berakunk egy Körte típusú statikus változót!
Működik? Igen, mert a Gyümölcs lehet Körte
A Körte típusú statikus változóba beraknánk
egy Gyümölcs típusú statikus változót!
Működik? Nem, mert a Körte csak Körte
lehet!
Értékadáskor változik a referencia (a dinamikus típus), de csak
olyan érték adható át, amelynek a statikus típusa megfelelő!
B IT MAN89/38
Statikus és dinamikus típus
Mi történik?
Gyümölcs a = new Körte("Vilmos");
Körte c = new Körte("Vilmos");
c = (Körte)a;
Körte
Gyümölcs
Alma
típus név érték
Körte c Körte Vilmos
Egy gyümölcs példány
lehet Gyümölcs, Alma,
vagy Körte típusú.
Alma példány csak
Alma típusú lehet.
Körte példány csak
Körte típusú lehet.
Gyümölcs a Körte Vilmos
Ha értékadáskor a jobb oldalon álló dinamikus típus
megegyezik a bal oldalon álló statikus típussal, akkor
konvertálással megoldható az értékadás.
Értékadáskor változik a referencia (a dinamikus típus), de csak
olyan érték adható át, amelynek a statikus típusa megfelelő!
B IT MAN89/39
Típuskonverzió referenciákra
Automatikus konverzió:
– Akkor lehetséges, ha a konvertálandó statikus típusa
azonos típus az eredmény statikus típusával vagy annak
leszármazottja. (Biztos, hogy a konvertálandó dinamikus
típusa is leszármazott vagy ugyanaz.)
Kikényszerített konverzió:
– Akkor alkalmazható, ha a konvertálandó statikus típusa
nem azonos vagy nem leszármazottja az eredmény
statikus típusának, de a dinamikus típusa igen.
– Az instanceof operátor a referencia dinamikus típusát
vizsgálja, segítségével megvizsgálhatjuk a konverzió előtt,
hogy végbemehet-e a konverzió.
Gyümölcs a = new Körte("Vilmos");
Körte c = new Körte("Vilmos");
System.out.println(a instanceof Körte); true
Gyümölcs a = new Körte("Vilmos");
B IT MAN89/40
s
B IT MAN89/41
A final minősítésű adattagok
A final minősítő többféle célra is használható a Java
nyelvben. Jelentése mindig "valami olyasmi, ami később nem
változtatható meg".
Final adattagok:
– Deklaráció: final típus azonosító=inicializáló_kifejezés;
– Az inicializáló kifejezés csak olyan elemeket tartalmazhat,
amelyek az addigi deklarációk ismeretében
feldolgozhatók.
public class Fém {String név;final double tömeg;
Fém(String név, double tömeg){this.név = név;this.tömeg = tömeg;
}}
‒ Miden példányosítás során
végrehajtódik, tehát a változó
értéke objektumként egyedi
lehet.
‒ Egyetlen metódus sem
változtathatja meg az értékét.
B IT MAN89/42
A final minősítésű adattagok
Static final adattagok:
– deklaráció:
• static final típus azonosító = inicializáló_kifejezés;
– Az inicializáló kifejezések csak konstansokat és olyan
static adattagokat tartalmazhat, amelyek már deklaráltak.
– Csak egyszer, az osztály inicializálása során hajtódik
végre, tehát a változó értéke az osztály miden példánya
számára ugyanaz.
– Egyetlen metódus sem változtathatja meg az értékét.
public class Személy {String név;static final int minimálbér = 185000;
}
B IT MAN89/43
A final minősítésű metódusok
Final metódus:
– Egy metódus is kaphat final minősítést.
– A final minősítésű metódust nem definiálhatja felül
egyetlen leszármazott osztály sem.
– Szerepe, hogy megakadályozza bizonyos viselkedés
formák megváltoztatását, ha az veszélyezteti a helyes
működését.
public class Kör {int sugár;
final double terület(){return sugár*sugár*Math.PI;
}}
B IT MAN89/44
Absztrakt metódus és osztály
Gyakran előfordul a tervezés során, hogy egy osztály szintjén
tudjuk, hogy valamilyen metódus szükséges lesz a
leszármazottakban, de még nem lehet megadni az
implementációját.
Ezért a Java nyelv megengedi törzs nélküli metódus
definiálását.
Az ilyen metódust az abstract minősítővel kell ellátni.
Ha az osztály tartalmaz absztrakt metódust, az osztályt is az
abstract minősítővel kell ellátni.
abstract class Termek{private String nev;
Termek(String nev){this.nev = new String(nev);
}abstract void kiir();
}
B IT MAN89/45
Absztrakt metódus és osztály
Az absztrakt metódusokra vonatkozó szabályok:
Absztrakt egy metódus, ha nincs törzse, megvalósítást csak a
felüldefiniálás során kap.
Absztrakt metódusnak nem lehet a módosítója a private, final,
static hiszen az ilyen módosítókkal ellátott metódusokat nem
lehet felüldefiniálni!
Absztrakt egy osztály, ha van legalább egy absztrakt metódusa
Absztrakt osztályt nem lehet példányosítani
Egy absztrakt osztály arra szolgál, hogy ős osztálya legyen további
osztályoknak
A leszármazott osztály(ok) feladata az absztrakt metódusok
felüldefiniálása
Absztrakt osztály gyermeke lehet absztrakt, ha nem minden
absztrakt metódust valósít meg
Az absztrakt osztály is használható referencia statikus típusaként
B IT MAN89/46
Absztrakt metódus és osztály
Az absztrakt metódusok szerepe: rögzít egy tervezési
döntést (szükséges metódusok halmaza), kényszeríti a
leszármazott osztály(ok) programozóját az így
meghatározott metódusok definiálására.
Hibalehetőségek:
– törzs nélküli metódus, abstract minősítő nélkül,
– absztrakt metódust tartalmazó osztály abstract minősítő
nélkül.
B IT MAN89/47
Teszt 6.
static
final
void
private
abstract
Mely kulcsszavak szerepelnek egy visszatérési
értékkel nem rendelkező, a leszármazott osztályban
felülírható, védett példánymetódus fejében?
B IT MAN89/48
Teszt 7.
public
private
abstract
final
static
extends
Mely kulcsszók szerepelhetnek egy osztálydefiníció
fejrészében?
B IT MAN89/49
Teszt 8.
Helyes vagy hibás az alábbi kód?
public abstract class Komplex {
int x, y, z;
abstarct Komplex(int x, int y, int z){
this.x = x;
this.y = y;
this.z = z;
}
}
B IT MAN89/50
Interfész
Technikailag:
– Egy olyan osztályféle, amely csak absztrakt metódusokat
és konstansokat tartalmazhat, tehát nem példányosítható.
– Nem örökléssel használjuk fel mint az absztrakt
osztályokat, hanem implementálással.
– Implementálás: megvalósítjuk az interfészben deklarált
metódusokat.
– Egy osztály implementálhat tetszőleges számú interfészt.
Tervezésileg:
– Egy viselkedési leírás, amelyet egy osztály megvalósít.
– Lehetővé teszi, hogy ne egy konkrét megvalósításhoz
(osztályhoz), hanem viselkedéshez (interfész) kössünk
dolgokat.
B IT MAN89/51
Interfész
Egy osztály interfészén a nyilvános elemeinek
összességét értjük, azokat, amelyek az osztály
megfelelő használatához szükségesek
Az információ rejtés elve miatt az interfész általában
csak metódusokból áll.
Szintaktikája hasonló az osztályhoz, de a class kulcsszó
helyett interface kulcsszót kell használni.
Az interfészt tartalmazó fájl nevének meg kell egyeznie a
kódban szereplő interfész névvel.
interface Nyomtathato{void nyomtat();
}
class Konyv implements Nyomtathato{String tartalom = "ABC";public void nyomtat(){
System.out.println(tartalom);}
}
B IT MAN89/52
Interfész
Minden interfész automatikusan abstract, ezt
módosítóval jelezni nem kell.
Egy interfész kiterjeszthet más interfészeket (extends).
Létezik többszörös interfész öröklés.
Az interfész nem tartalmaz végrehajtható kódot, azt a
megvalósító osztályban (implements) kell megadni.
Konvenció, hogy az interfészek neve „I”-vel kezdődik.
[módosító] interface Iazonosító extends If1, If2 { [elemek deklarációja]
}
B IT MAN89/53
Interfész
Interfész implementálása:
Szabályok:
Ha egy osztály implementál egy interfészt, akkor köteles
annak minden metódusát implementálni
Az implementált elemeket nem módosíthatja
Metódusok esetében a fejlécnek teljesen egyeznie kell
Azonos nevű elemet az öröklődés során és az implementálás
során nem kaphat meg
[módosító] class osztálynév implements If1, If2() { }
B IT MAN89/54
Interfész
Tagok:
– Csak konstansai vagy abstract tagjai lehetnek.
• Konstans: automatikusan public static final módosítóval
rendelkeznek, de kiírhatók a módosítók.
• Metódusok: automatikusan public abstract módosítóval
rendelkeznek, a public kiírható, az abstract nem
ajánlott.
• Más módosítója nem lehet (pl. static, final, stb.).
Interfész használata:
– Egy interfész új referencia típust vezet be -> mindenhol
használható, ahol egy osztály.
– Változó deklarációban szerepelhet.
– Értékül minden olyan osztály objektumának felveheti a
referenciáját, amely megvalósítja az interfészt!
B IT MAN89/55
Interfész – Példák
A ref;ref = new B(); //OK! ref = new C(); //OK! ref = new D(); //NO! Hibás!ref = new A(); //NO! Hibás!
A x = new B();System.out.println(ref instanceof A);System.out.println(ref instanceof C);
truetrue
public interface A { … }public class B implements A { … }public class C implements A { … }public class D { … }
B IT MAN89/56
Interfész – Példák
I1 a = new A(); //OK! I2 b = new A(); //OK! a = b; //OK! Automatikus típuskonverzió
b = (I2)a; //OK! Kikényszerített típuskonverzió
A c = (A)a; //OK! Kikényszerített típuskonverzió
a = new B(); //OK! b = (I2)a; //NO! Hibás!
interface I1 {…}interface I2 extends I1 {…}class A implements I2 {…}class B implements I1 {…}
B IT MAN89/57
Teszt 9.
Egy interfészben metódusfejeket és konstansokat
definiálhatunk.
Az interfész metódusai csak példánymetódusok
lehetnek
Egy interfésznek az osztályhoz hasonlóan csak egy
interfész őse lehet.
Az interfészekből példányok hozhatók létre,
akárcsak az osztályokból.
Jelölje meg az összes igaz állítást!
B IT MAN89/58
Teszt 10.
Az adott a Base interfész mellett melyik kód fordul le?
interface Base { boolean m1 (); byte m2(short s);
}
abstract class Class2 implements Base {
public boolean m1() { return (7 > 4); }
}
interface Base2 implements Base { }
abstract class Class2 extends Base {
public boolean m1() { return true; }
}
class Class2 implements Base {
boolean m1() { return false; }
byte m2(short s) { return 42; }
}
B IT MAN89/59
Generikus típusok, metódusok
B IT MAN
B IT MAN89/60
Generikus típusok, metódusok
Általános jellegű, nem konkrét típust használó típusok,
metódusok definiálása.
– Tipikus példa: adattároló osztály
– Régebbi megoldás: Object referencia használata.
public class Tarolo {private Object object;
public void set(Object object) {this.object = object;
}public Object get() {
return object;}
}
B IT MAN89/61
Generikus típusok, metódusok
A Tarolo osztályt egészek tárolására használjuk
– Véletlenül belekerül egy String
– Az eredeti típusos objektum visszakapásához castolni kell
– A program lefordul, a hiba csak futtatáskor derül ki!
public class TaroloPrg {public static void main(String args[]) {
Tarolo t = new Tarolo();
t.set(3);int i = (Integer)t.get();
t.set("Retek");int k = (Integer)t.get();
}}
c:\Java8>java TaroloPrg
Exception in thread "main" java.lang.ClassCastException: java.lang.String
cannot be cast to java.lang.Integer at TaroloPrg.main(TaroloPrg.java:7)
B IT MAN89/62
Generikus típusok, metódusok
Megoldás: generikus "típussal paraméterezett típus"
használata
public class GenericTarolo<T> {private T t;
public void set(T t) {this.t = t;
}
public T get() {return t;
}}
Konvenció:
Paraméterként használt
típusok jelölése:
• E - Elemek
• K - Kulcs
• N - Szám
• T - Típus
• V - Érték
B IT MAN89/63
Generikus típusok, metódusok
A GenericTarolo osztályt egészek tárolására használjuk
– Az adat közvetlenül kinyerhető, nincs cast!
– Véletlenül belekerül egy String, a hiba már fordításkor jelentkezik!
public class GTPrg {public static void main(String args[]) {
GenericTarolo<Integer> gt = new GenericTarolo<Integer>();gt.set(3);int i = gt.get();gt.set("Retek");
}}
c:\Java8>javac -d . GTPrg.java
GTPrg.java:5: set(java.lang.Integer) in GenericTarolo<java.lang.Integer>
cannot be applied to (java.lang.String)
gt.set("Retek");
^
B IT MAN89/64
Generikus típusok, metódusok
public class GenArray {
public static <E> void printArray(E[] inputArray) {for(E elem : inputArray)
System.out.printf("%s ", elem);System.out.println(); //üres elválasztó sor kiírása
}
public static void main(String args[]) {Integer[] intArray = { 1, 2, 3, 4, 5 };Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println("Az egész típusú tömb tartalma:");printArray(intArray);
System.out.println("\nA valós típusú tömb tartalma:");printArray(doubleArray);
System.out.println("\nA karakter típusú tömb tartalma:");printArray(charArray);
}}
B IT MAN89/65
Hibakezelés
B IT MAN89/66
Hiba, biztonságos program
Szintaktikai hiba
Szemantikai hiba
Biztonságos program
A szemantikai hibákat megpróbálja lekezelni a belőlük
következő hibákkal együtt
Ennek módja: kivételkezelés
imt i = 0;system.out.Println('alma');for (int i = 0, i<= 10, i++)...
int a=0, b=10/a;x1=(-b+Math.sqrt(b*b-4*a*c))/2*a;args[++i]
B IT MAN89/67
Kivételkezelés
Fogalma: A hibakezelés egy formája, amelyben
elválasztható a hibalekezelő kódrészlet a normál
működés kódjától, valamint a jelezhetjük a kódunkban
előforduló hibákat és előírhatjuk kezelésüket a kódunkat
használó kód számára.
Kivételek keletkezése
– Kivétel létrejöhet egy végrehajtás során előforduló hiba
hatására (I/O hiba, tömbindex túllépés, stb.), valamint saját
magunk is létrehozhatunk kivételeket.
– A kivétel létrejöttét a kivétel megdobódásának nevezzük.
– A kivétel elkapását a kivétel lekezelésének nevezzük.
B IT MAN89/68
Kivételkezelés
Kivételek: Javaban a kivételek objektumok.
A kivétel osztályok az Exception osztály leszármazottai
Fajtái:
– Kötelezően lekezelendő kivételek: a fordító ellenőrzi, hogy
ezeket lekezeljük-e. Például az I/O műveletek során
előforduló kivételek.
– Nem kötelezően lekezelendő kivételek: nem kötelező
lekezelni. Ezek a RuntimeException leszármazottai, ami
viszont az Exception leszármazottja. Például a null
referencia hiba, tömb index túllépés, stb.
– A saját kivételosztályokat ez alapján vagy az Exception
osztályból származtatjuk (közvetve, közvetlenül) (ekkor
kötelező lekezelni) vagy a RuntimeException-ból (ekkor
nem kötelező lekezelni).
B IT MAN89/69
Kivételosztályok – néhány fontosabb
Ellenőrzött kivételek
Nem ellenőrzött kivételek
IOException Ki- és bemeneti hibák esetén váltódik ki, pl. konzolról való
beolvasáskor.
FileNotFoundException Az IOException egyik alkivételosztálya. Akkor kapjuk például, ha nem
létező fájlba próbálunk írni.
EOFException Fájl végét jelző kivétel. Szintén az IOException alosztálya.
RuntimeException Valamennyi futásidejű kivétel ősosztálya.
NullPointerException Olyan esetben kapjuk, ha null értékű, azaz inicializálatlan változóra
vagy objektumra hivatkozunk.
IndexOutOfBoundsExcep-
tion
Túlindexelést jelző kivétel. Akkor kapjuk, ha egy tömb, karakterlánc,
vagy más indexelhető szerkezet nem létező indexére hivatkozunk.
ArithmeticException Aritmetikai műveletek hibájakor kapjuk, például nullával való osztáskor.
NumberFormatException Akkor kapjuk például, ha nem megfelelő számot tartalmazó
karakterláncot próbálunk szám típusúvá konvertálni.
IllegalArgumentExcep-
tion
Akkor váltódik ki, ha egy metódust nem megfelelő paraméterekkel
hívunk.
B IT MAN89/70
Kivételkezelés
A védett kódot try blokkban helyezzük el:
try { utasítások }
Az első kivételt kiváltó utasítással befejeződik a try blokk
végrehajtása, létrejön egy kivétel objektum. Fontos: a try
blokk kivételt kiváltó utasítása utáni utasítások tehát
mindig kimaradnak!
try {
kód, ami kiválthat egy kivételtX
} catch ( ) {Kivétel típusa Azonosító
további utasítások
B IT MAN89/71
Kivételkezelés
A kivétel lekezelését szolgáló utasítások catch
blok(kok)ban helyezkednek el.
catch (típus, azonosító) { utasítások }
A catch minden esetben a try blokkot követi, nem lehet
köztük más utasítás.
Egy try blokkhoz tartozhat több catch is. Mindig a
szűkebb kivételt követi a bővebb kivétel lekezelése.
} catch ( ) {
kód, ami a kivétel kiváltódásakor lefut
Kivétel típusa Azonosító
}
} catch ( ) {
kód, ami a kivétel kiváltódásakor lefut
Kivétel típusa Azonosító
B IT MAN89/72
Kivételkezelés
finally: A cacth(ek) után szerepelhet. Az utolsó catch
blokk és a finally blokk között nem lehet más utasítás.
Minden esetben lefut:
– Ha kivétel keletkezett a try blokkban, egy catch blokk
végrehajtása után.
– Ha nem volt kivétel, a try blokk utolsó utasítása után.
} finally {
} catch ( ) {
kód, ami a kivétel kiváltódásakor lefut
Kivétel típusa Azonosító
try {
kód, ami kiválthat egy kivételtX
kód, ami mindig lefut}
B IT MAN89/73
Kód belépési pont
try {
kód, ami kiválthat egy kivételtX
} catch ( ) {
kód, ami a kivétel kiváltódásakor lefut
Kivétel típusa Azonosító
Kód kilépési pont
} finally {
kód, ami mindig lefut}
Kód végrehajtás
kivétel esetén
Kód végrehajtás
hibamentes
esetben
B IT MAN89/74
Kivételkezelés
A Java kivételkezelése nyitott, ami azt jelenti, hogy bárki
létrehozhat saját névvel és funkcionalitással ellátott
kivételosztályokat, amelyeket célszerű az Exception
osztályból származtatni. Az új kivételosztályok nevében
célszerű az "Exception" szót is szerepeltetni, hogy
utaljon annak szerepére.
Kivétel dobása (throw utasítás)
– throw kivételobjektumref;
• pl: throw new IOException("Hiba van");
– throw sajátKivételosztályNév("Saját hibaüzenet");
B IT MAN89/75
Kitérő – verem adatszerkezet
Verem:
– Verem esetén azt az elemet vehetjük ki legelőször,
amelyiket utoljára tettük be. Működési módja miatt LIFO
(last in first out) adatszerkezetnek nevezik.
– Műveletek: berakás, kivétel
A
B
C
C, B, A A, B, C
Berak Kivesz
3. 2. 1. 3. 2. 1.
B IT MAN89/76
Kivételkezelés – Példa
public class Verem_Exception extends Exception {
public Verem_Exception(String hibauzenet){super(hibauzenet);
}}
Készítsünk egy komplett verem kezelő alkalmazást
– Ha a verembe nem lehet betenni, vagy nem lehet belőle
kivenni adatot, használjunk hibakezelést
– A hibakezeléshez írjunk saját hiba osztályt
B IT MAN89/77
Kivételkezelés – Példa
public class Verem{private final static int MERET = 3;private int[] verem = new int[MERET];private int mutato = 0;
public void betesz(int i) throws Verem_Exception {if (mutato < MERET) {
verem[mutato] = i;System.out.println("A szám: ("+i+") a verembe helyezve!");mutato++;
} elsethrow new Verem_Exception("A verem megtelt!");
}
public int kivesz() throws Verem_Exception {if (mutato == 0)
throw new Verem_Exception("A verem üres!");mutato--;int i = verem[mutato];System.out.println("A szám: ("+i+") a veremből kivéve!");return i;
}}
B IT MAN89/78
public class VeremPrg{public static void main(String args[]) {
Verem v = new Verem();try {
v.betesz(21);v.betesz(52);v.betesz(77);v.betesz(99);
} catch (Verem_Exception ve) {System.err.println(ve);
}
System.out.println();try {
v.kivesz();v.kivesz();v.kivesz();v.kivesz();
} catch (Verem_Exception ve) {System.err.println(ve);
}}
}
B IT MAN89/79
Kivételkezelés
Kivétel terjedése
– A kivétel nem képes tovább terjedni egy metódusblokkból,
hacsak a metódus fejlécében nincs megadva a kivétel
típusa vagy annak őse.
– Ha egy metódus fejlécében kötelezően lekezelendő
kivételtípus van megadva, akkor a hívását kötelező olyan
try utasításba ágyazni (közvetlenül vagy közvetve), amelyik
lekezeli a kivételtípust.
– Mivel a catch blokkok keresése sorban történik mindig
előbbre kell írni azt a catch blokkot, amelyik egy
leszármazott típust kap el és csak utána azt, amelyik az őst.
– A utolsó catch blokként lehet írni egy Exception-t elkapót,
hiszen az minden kivételt képes elkapni.
B IT MAN89/80
Teszt 11.
Helyes vagy hibás az alábbi kód?
public class Teszt {
public static void main(String args[ ]) {
int x = new int(5);
}
}
Miért?
Helyes
Hibás
B IT MAN89/81
Teszt 12.
Mit ír ki a kód?
public class SuperClass {
int i, j;
SuperClass(int i, int j) {
this.i = i;
this.j = j;
}
SuperClass() {
this(2, 3);
}
}
public class Program extends SuperClass {
public Program() {
System.out.println(i + j);
}
public static void main(String[ ] args) {
new Program();
}
}
0
5
null
Szintaktikailag hibás, így
nem fut le a kód.
B IT MAN89/82
Teszt 13.
Egy konstruktorból meghívható az osztály egy
másik konstruktora.
Egy objektum létrehozásakor az öröklési ág minden
osztályának lefut legalább egy konstruktora.
Ha a konstruktor első sorában nem szerepel this()
vagy super() hívás, akkor futási hiba keletkezhet
Az osztályadatokat csak a konstruktorban lehet
inicializálni.
A konstruktor a leszármaztatott osztályban
felüldefiniálható
Jelölje meg az összes igaz állítást!
B IT MAN89/83
Teszt 14.
Milyen típusú kivételt dob a parseInt() metódus, ha
illegális adatot kap?
NumberFormatError
NumberException
NumberFormatException
ArithmetricException
B IT MAN89/84
Teszt 15.
Helyes vagy hibás az alábbi kód?
public class Fut {public static void main(String[] args) {
try {} finally {
System.out.println("BB");}
}}
Helyes
Hibás
B IT MAN89/85
Teszt 16.
Helyes vagy hibás az alábbi kód?
public class Fut {public static void main(String[] args) {try {
System.out.println("BB");} catch (Exception e) {
System.out.println(e.getMessage());} catch (ArithmeticException a) {
System.out.println(a.getMessage());}
}}
Helyes
Hibás
B IT MAN89/86
Teszt 17.
Az alábbi kód egy A.java nevű fájlban van. Mi történik, ha
megpróbáljuk lefordítani?
public class A { public void m1() {System.out.print("A.m1,");} protected void m2() {System.out.print("A.m2,");} private void m3() {System.out.print("A.m3,");} void m4() {System.out.print("A.m4,");}
} class B {
public static void main(String[] args) { A a = new A(); a.m1(); a.m2(); a.m3(); a.m4();
} }
Lefordul, minden OK.
Nem fordul, mert egy fájlban csak egy
osztály lehet
Nem fordul, mert hiba van az A osztályban
Nem fordul, mert hiba van a B osztályban
B IT MAN89/87
Teszt 18.
Az alábbi kód egy A.java nevű fájlban van. Lefordítjuk.
Hogyan indítjuk el a programot?
public class A { public void m1() {System.out.print("A.m1,");} protected void m2() {System.out.print("A.m2,");} public void m3() {System.out.print("A.m3,");} void m4() {System.out.print("A.m4,");}
} class B {
public static void main(String[] args) { A a = new A(); a.m1(); a.m2(); a.m3(); a.m4();
} }
Sehogy, csak az A osztály fordul le.
java A
java A.B
java B
B IT MAN89/88
Ficsor Lajos elektronikus jegyzetei
Elek Tibor elektronikus jegyzetei
Fenyvesi Tibor, Szabó László elektronikus anyagai
www.tutorialspoint.com/java oldal anyagai
prog.hu oldal anyagai
Nyékiné G. Judit (szerk.): JAVA 2 útikalauz programozóknak,
ELTE TTK Hallgatói Alapítvány, Budapest, 1999
Daniel J. Berg, J. Steven Fritzinger: JAVA felsőfokon,WILEY,
1999
Joshua Bloch: Hatékony Java, 2008
Felhasznált irodalom
B IT MAN
B IT MAN89/89
VÉGEVÉGE