16. Interfészek

Az interfész olyan viselkedéseket definiál, amelyet az osztályhierarchia tetszőleges osztályával megvalósíthatunk. Egy interfész metódusok halmazát definiálja, de nem valósítja meg azokat. Egy konkrét osztály megvalósítja az interfészt, ha az összes metódusát megvalósítja.

Definíció: Az interfész implementáció nélküli metódusok névvel ellátott halmaza.
Mivel az interfész a megvalósítás nélküli, vagyis absztrakt metódusok listája, alig különbözik az absztrakt osztálytól. A különbségek:

  • Az interfész egyetlen metódust sem implementálhat, az absztrakt osztály igen.
  • Az osztály megvalósíthat több interfészt, de csak egy ősosztálya lehet.
  • Az interfész nem része az osztályhierarchiának. Egymástól "független" osztályok is megvalósíthatják ugyanazt az interfészt.

Ebben a fejezetben egy olyan példaprogramot fogjuk használni, ami a Tervezési minták (Design Patterns) között szokás emlegetni megfigyelő (Observer) néven. Ez az osztály megengedi más osztályoknak, hogy regisztrálják magukat bizonyos adatai változásának figyelésére. A StockApplet osztály fog megvalósítani egy olyan metódust, amivel regisztrálni tud a változás figyeléséhez:

public class StockMonitor {
     public void watchStock(StockWatcher watcher,
                            TickerSymbol tickerSymbol,
                            BigDecimal delta) {
     ...
     }
}

Az első paraméter egy StockWatcher objektum. A StockWatcher annak az interfésznek a neve, amelyet hamarosan látni fogunk. Az interfész egyetlen valueChanged nevű metódust definiál. Egy objektum akkor tudja magát megfigyelőként regisztrálni, ha az osztálya megvalósítja ezt az interfészt. Amikor a StockMonitor osztály érzékeli a változást, meghívja a figyelő valueChanged metódusát.

16.1 Interfész definiálása

A következő ábra bemutatja az interfész definíció két összetevőjét: az interfész deklarációt és a törzset.

Interfész definiálása

A StockWatcher interfész deklarálja, de nem implementálja a valueChanged metódust. Az interfészt megvalósító osztályok fogják a metódust implementálni.

Interfész deklaráció

A következő ábra az interfész deklaráció minden részét bemutatja:

Interfész deklaráció

Az interfész deklarációban két elem kötelező: az interface kulcsszó és az interfész neve. Ez után szerepelhetnek a szülőinterfészek.

Az interfész törzs

Az interfész törzs metódus deklarációkat tartalmaz ';'-el lezárva. Minden deklarált metódus értelemszerűen publikus és absztrakt (bár maguk a kulcsszavak nem írhatók ki).
Az interfész tartalmazhat konstans deklarációt is. Minden konstans értelemszerűen publikus, statikus és végleges. (A kulcsszavak itt sem írhatók ki.) Nem használhatók a transient, volatile, synchronized, private és protected módosítók sem.

16.2 Interfészek implementálása

Egy interfész viselkedési formákat definiál. Az interfészt megvalósító osztály deklarációjában szerepel az implements záradék. Az osztály akár egy vagy több interfészt is megvalósíthat. (Az interfészek között megengedett a többszörös öröklődés.)

Konvenció: az implements záradék az extends záradékot követi, ha mindkettő van.
A következő példa applet implementálja a StockWatcher interfészt.

public class StockApplet extends Applet
                         implements StockWatcher {

    public void valueChanged(TickerSymbol tickerSymbol,
                             BigDecimal newValue) {
        switch (tickerSymbol) {
            case SUNW:
                ...
                break;
            case ORCL:
                ...
                break;
            case CSCO:
                ...
                break;
            default:
                // handle unknown stocks
                ...
                break;
        }
    }
}

Amikor egy osztály megvalósít egy interfészt, akkor alapvetően aláír egy szerződést. Az osztálynak implementálni kell az interfészben és szülőinterfészeiben deklarált összes metódust, vagy az osztályt absztraktként kell deklarálni. (Az ilyen absztrakt osztályoknak csak akkor lehet nem absztrakt egy leszármazottja, ha az ezen az öröklési szinten meg nem valósított metódusokat már maradéktalanul megvalósítja.)

A StockApplet megvalósítja a StockWatcher interfészt, azaz szolgáltatásként nyújtja a valueChanged metódust.

Az interface használata típusként

Amikor új interfészt definiálunk, referenciát definiálunk egy új adattípushoz. Az interfész nevét akárhol lehet használni, ahol egyéb adattípus is előfordulhat.

public class StockMonitor {
    public void watchStock(StockWatcher watcher,
                           TickerSymbol tickerSymbol,
                           BigDecimal delta) {
    ...
    }
}

16.3 Ellenőrző kérdések

Igaz vagy hamis? Indokolja!

  • Az interfész csak metódust tartalmazhat, változót nem.
  • Minden osztály legfeljebb egy interfészt implementálhat.
  • Az interfész összes változója implicit static.
  • Az interfésznek nincs konstruktora.
  • Az interfész összes metódusa implicit public.
  • Ha egy osztály megvalósít egy interfészt, azt a uses kulcsszóval kell jelezni.
  • Az interfész összes metódusa implicit abstract.
  • Az interfész összes változója implicit public.
  • Az interfészt megvalósító osztálynak minden, az interfészben deklarált metódust implementálni kell.
  • Létre lehet hozni interfész-referenciát.
  • Minden interfésznek van őse.
  • Az interfész összes változója implicit final.
  • Minden interfészt legalább egy osztályban meg kell valósítani.
  • Az interfész metódusainak nincs törzse.
  • Az interfész és az absztrakt osztály között nincs lényeges különbség.