You are on page 1of 8

Polimorfizmus

zA harmadik lényeges OOP tulajdonság az


adatabsztrakció és öröklődés után
z Interfész és implementáció: Szétválasztja a mit a
Polimorfizmus hogyan-tól (típusokra értendő)

Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák


2002. 03. 25. 115 2002. 03. 25. 116
© Ferenc Rudolf © Ferenc Rudolf

Példa „Elfelejteni” a típust?


z Az előző példában a tune(flute) hívás során
class Note {
private int value;
private Note(int val) { value = val; }
public static final Note
MIDDLE_C = new Note(0),
„elveszik” a típus, mert a metódus Instrument-
C_SHARP = new Note(1),
B_FLAT = new Note(2); et vár de Wind van átadva
}
class Instrument { – Egyszerűbb lenne ha a tune metódus Wind-et várna?
public void play(Note n) {

}
System.out.println("Instrument.play()");
– Nem, mert akkor minden egyes hangszerre kellene
}
class Wind extends Instrument {
public class Music { külön tune metódus!
public static void tune(Instrument i) {
public void play(Note n) {
System.out.println(
}
i.play(Note.MIDDLE_C);
– Sőt, ha újabb hangszert szeretnénk hozzáadni, akkor
"Wind.play()");
}
public static void main(String[] args) {
Wind flute = new Wind();
mindig új metódus is kell (karbantarthatóság)!
}
tune(flute); // Upcasting
}
}

Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák


2002. 03. 25. 117 2002. 03. 25. 118
© Ferenc Rudolf © Ferenc Rudolf
Kései kötés Bővíthetőség
z Honnan tudja a fordító, hogy melyik objektum zA polimorfizmusnak köszönhetően tetszőleges
play metódusát hívja? számú új hangszert felvehetünk a tune metódus
z Nem tudja! megváltoztatása nélkül
z Csak futás közben derül ki az objektum típusa z Egy jól megtervezett OO programban ezt a
alapján modellt követik, vagyis az objektumok az
public class Music {
public static void tune(Instrument i) {
interfészek segítségével kommunikálnak
}
i.play(Note.MIDDLE_C);
egymással
public static void main(String[] args) {
Wind flute = new Wind();
tune(flute); // Upcasting
}
}

Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák


2002. 03. 25. 119 2002. 03. 25. 120
© Ferenc Rudolf © Ferenc Rudolf

Absztrakt osztályok és metódusok Absztrakt (folyt.)


 Az előző példában az Instrument ősosztályban  Kulcsszó: abstract
szereplő metódusok valójában „álmetódusok”  Absztrakt osztály: abstract class Instrument {/*...*/}
– Ha ezek véletlenül meghívódnak, akkor valami hiba van a – Nem példányosítható (fordítási hiba)
programban, mert ezeknek a szerepe az, hogy interfész
– Közös interfészt biztosít a leszármazottaknak
legyen
– Lehetne programfutás közben kiíratni, hogy hiba van, de
 Absztrakt metódus: abstract void f();

ennek az ellenőrzéséhez sok tesztelés szükséges – Csak deklarációja van (nincs definíciója – törzse)
– Magából az ősosztályból valójában nem kellene, hogy  Ha egy osztálynak van legalább egy absztrakt
létrejöjjön objektum metódusa, akkor neki is absztraktnak kell lennie
 Ezért bevezették az absztrakt osztályokat és  Egy osztály lehet absztrakt akkor is, ha nincs absztrakt
metódusokat (fordítási időbeni ellenőrzés) metódusa
Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák
2002. 03. 25. 121 2002. 03. 25. 122
© Ferenc Rudolf © Ferenc Rudolf
Futás közbeni típusazonosítás
RTTI – Run-time type identification
z Upcast (ősre konvertálás)
– Elveszítjük a konkrét típust
– A konverzió biztonságos Interfészek és belső osztályok
z Downcast (leszármazottra konvertálás)
– Jó lenne visszanyerni a konkrét típust
– A konverzió egyéb nyelvekben nem biztonságos
– Java-ban ellenőrizve van (RTTI): Ha nem megfelelő
típusra próbálunk downcast-olni akkor egy
ClassCastException típusú kivétel dobódik

Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák


2002. 03. 25. 123 2002. 03. 25. 124
© Ferenc Rudolf © Ferenc Rudolf

Interfészek Interfaces Interfészek (folyt.)


z Interfész osztály: Teljesen absztrakt osztály z Az implements kulcsszóval lehet származtatni
– Kulcsszó: interface belőle (implementálni)
– Metódus deklarációk (törzs nélkül, impliciten interface Instrument {
int i = 5; // static & final
public) void play(); // Automatically public
String what();
– Mezők (impliciten static és final) }
void adjust();

– Lehetővé teszi a „többszörös öröklődés”-t class Wind implements Instrument {


public void play() {

z Csak egy formát ad meg implementáció nélkül }


System.out.println("Wind.play()");

public String what() { return "Wind"; }


z Egy „protokoll”-t valósít meg osztályok között }
public void adjust() {}

Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák


2002. 03. 25. 125 2002. 03. 25. 126
© Ferenc Rudolf © Ferenc Rudolf
Interfészek (folyt.) „Többszörös öröklődés”
z Interfész vagy absztrakt osztály? z Mivel az interfészek nem foglalnak tárterületet,
– Ha ősosztályt készítünk, akkor mindig kezdjük lehetővé válik a biztonságos többszörös
azzal, hogy interfész lesz öröklődés
– Ha mégis szükség lesz az ősosztály szintjén z Nem „igazi” többszörös öröklődés (mint pl. a
metódusokat implementálni vagy mezőket C++-ban)
hozzáadni akkor módosítsuk absztrakt osztályra
(esetleg konkrét osztályra) z Max. egy db. „igazi” osztály lehet az ősök
között, a többi interfész kell legyen
z Interfész osztályok is származhatnak
egymásból, ezzel új interfészt kapunk
Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák
2002. 03. 25. 127 2002. 03. 25. 128
© Ferenc Rudolf © Ferenc Rudolf

„Többszörös öröklődés” (folyt.) Konstansok csoportosítása


z Példa: interface CanFight {
void fight();
z Mivel az interfészek mezői automatikusan
}
static és final-ok, jó eszköz arra, hogy
konstansokat csoportosítsunk (hasonlít a C++-os
interface CanSwim {
void swim();
}
Enum-ra) public interface Months {
interface CanFly {
int
void fly();
JANUARY = 1, FEBRUARY = 2, MARCH = 3,
}
APRIL = 4, MAY = 5, JUNE = 6, JULY = 7,
AUGUST = 8, SEPTEMBER = 9, OCTOBER = 10,
class ActionCharacter {
NOVEMBER = 11, DECEMBER = 12;
public void fight() {}
}
}

class Hero extends ActionCharacter public final class Test {


implements CanFight, CanSwim, CanFly { public static void main(String[] args) {
public void swim() {} System.out.println(Months.MAY);
public void fly() {} }
} }

Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák


2002. 03. 25. 129 2002. 03. 25. 130
© Ferenc Rudolf © Ferenc Rudolf
Belső osztályok Inner classes Belső osztályok (folyt.)
z Osztályon- vagy metóduson belüli osztályok z Példa: public class Parcel {
class Contents {
private int i = 11;
– Logikailag összetartozó osztályok csoportosítása public int value() { return i; }
}
– Megadható a láthatóságuk class Destination {
private String label;
Destination(String whereTo) {
– Máshól nem használt algoritmus elrejtése a label = whereTo;
}
külvilágtól String readLabel() { return label; }
}
– A belső osztályból elérhetőek a „körülvevő” osztály public void ship(String dest) {
Contents c = new Contents();
elemei (hacsak nem static a belső osztály) Destination d = new Destination(dest);
System.out.println(d.readLabel());

– .class fájlnév: OuterClass$InnerClass.class


}
public static void main(String[] args) {
Parcel1 p = new Parcel1();
z Nem kompozíció! }
p.ship("Tanzania");

Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák


2002. 03. 25. 131 2002. 03. 25. 132
© Ferenc Rudolf © Ferenc Rudolf

Kollekciók (konténerek) Collections


z Csak nagyon egyszerű program Containers
esetében van előre meghatározott
Objektumok tárolása: számú objektum ismert élettartammal
z Általában ez csak futási időben derül ki:
Kollekciók (konténerek) – Kell, hogy legyen lehetőség objektumokat
létrehozni bármikor, bárhol
– Ezeknek nem lehet mindig nevet adni…
z A megoldás: Kollekciók (konténerek)
– Beépített típus: tömb (array)
– Konténer osztályok a java.util könyvtárból
Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák
2002. 03. 25. 133 2002. 03. 25. 134
© Ferenc Rudolf © Ferenc Rudolf
Tömbök Arrays Az Arrays osztály
z Már bemutattuk a tömbök használatát z A java.util könyvtár része
z Miért jobb a tömb a többi konténernél? z Statikus metódusokat tartalmaz, amik segítséget
– Hatékonyság: Konstans idejű elérés, de fix a méret
nyújtanak a tömbkezelésben:
(flexibilis tömb: ArrayList konténer) – equals() – tömbök egyenlősége
– fill() – tömb feltöltése adott értékkel
– Típus: Nem veszíti el a típust – adott típusú
elemeket tárol, nem Object-eket – sort() – tömb rendezése
– binarySearch() – tömbben keresés
z Először mindig próbáljunk meg tömböt
– asList() – List típusú listát készít belőle (később)
használni, és csak akkor válasszunk másik
z Mindegyik meg van valósítva (overload)
konténert, ha korlátba ütközünk
minden primitív típusra és az Object-re
Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák
2002. 03. 25. 135 2002. 03. 25. 136
© Ferenc Rudolf © Ferenc Rudolf

Tömbök egyenlősége, feltöltése Tömbök rendezése


z Az Arrays osztály részei z Az általános rendezőalgoritmusoknak az elemek
 equals() – Az egész tömböt összehasonlítja, típusaitól függetleneknek kell lenniük
elemenként – Össze kell, hogy tudjon hasonlítania két elemet
 fill() – Tömb feltöltése adott értékkel – Típusoktól függetlenül kell, hogy működjön

z Példa: public class ComparingArrays {


z Callback technikával oldható meg
public static void main(String[] args) {
int[] a1 = new int[10]; – Az elem saját maga hasonlítja magát össze egy
int[] a2 = new int[10];
Arrays.fill(a1, 47); ugyanolyan típusú másik elemmel
Arrays.fill(a2, 47);

}
System.out.println(Arrays.equals(a1,a2)); – Két módszer van rá: Comparable és Comparator
}

Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák


2002. 03. 25. 137 2002. 03. 25. 138
© Ferenc Rudolf © Ferenc Rudolf
Tömbök rendezése (folyt.) Tömbök rendezése (folyt.)
z „Természetes módszer”: Comparable z Példa:
z A java.lang.Comparable interfész public class CompType implements Comparable {
int i;

implementálása public CompType(int n) {


i = n;
}
z Egyetlen metódusa van: compareTo() public int compareTo(Object rv) {
int rvi = ((CompType)rv).i;
return (i < rvi ? -1 : (i == rvi ? 0 : 1));
– Egy objektumot vár paraméterül }
public static void main(String[] args) {
– Visszatérési érték: <0, ha az aktuális objektum CompType[] a = new CompType[10];
/* fill the array */
kisebb mint az argumentum; =0 ha egyenlő és >0 ha }
Arrays.sort(a);

nagyobb, mint az argumentum }

Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák


2002. 03. 25. 139 2002. 03. 25. 140
© Ferenc Rudolf © Ferenc Rudolf

Tömbök rendezése (folyt.) Tömbök rendezése (folyt.)


 Másik módszer: Comparator z Példa:
 Ha nem implementálta az osztály a Comparable class CompTypeComparator implements Comparator {
interfészt public int compare(Object o1, Object o2) {
int i1 = ((CompType)o1).i;

 Egy külön osztályt kell létrehozni, ami a int i2 = ((CompType)o2).i;


return (i1 < i2 ? -1 : (i1 == i2 ? 0 : 1));
java.lang.Comparator interfészt implementálja }
}

 Két metódusa van: compare() és equals() public class ComparatorTest {


– Általában csak a compare()-t kell implementálni, mert az public static void main(String[] args) {
CompType[] a = new CompType[10];
Object ősosztály implementálja a másikat /* fill the array */
Arrays.sort(a, new CompTypeComparator());
– Két objektumot vár paraméterül }
}
– Visszatérési érték: <0, ha az első argumentum kisebb; =0 ha
egyenlő és >0 ha nagyobb mint a második objektum

Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák


2002. 03. 25. 141 2002. 03. 25. 142
© Ferenc Rudolf © Ferenc Rudolf
Tömbben keresés Tömbben keresés (folyt.)
z Csak rendezett tömbben lehet keresni! z Példa:
 Arrays.binarySearch() – bináris keresés public class ArraySearching {
public static void main(String[] args) {
– Visszatérési érték: ≥0 ha megtalálta (a keresett elem int[] a = new int[100];
/* fill the array */
tömbindexe); <0 ha nem (melyik elem előtt kellene, Arrays.sort(a);
/*...*/
hogy legyen) int location = Arrays.binarySearch(a,19);
if(location >= 0) {
– Ha több elem is megfelel a keresésnek, akkor }
/* element found */

bizonytalan, hogy melyiket találja meg (ilyenkor }

használjunk inkább TreeSet-et, lásd később)


}

– Ha Comparator-ral lett rendezve, akkor meg kell


adni ugyanazt a Comparator objektumot a
keresésnek is
Rendszerfejlesztés előadás fóliák Rendszerfejlesztés előadás fóliák
2002. 03. 25. 143 2002. 03. 25. 144
© Ferenc Rudolf © Ferenc Rudolf

Tömbök másolása
 System.arraycopy() statikus metódus
z Meg van valósítva minden primitív típusra és az
Object-re (csak a referenciák másolódnak!)
public class CopyingArrays {
public static void main(String[] args) {
int[] i = new int[25];
int[] j = new int[25];
/*...*/
System.arraycopy(i, 0, j, 0, i.length);
/*...*/
}
}

Rendszerfejlesztés előadás fóliák


2002. 03. 25. 145
© Ferenc Rudolf

You might also like