Interfészek
Interface Java egy kicsit olyan, mint a Class, de jelentős különbség: egy interface
lehet csak method aláírások, mezők és az alapértelmezett mód. A Java 8 óta alapértelmezett módszereket is létrehozhat. A következő blokkban láthat egy példát az interfészre:
public interface Vehicle { public String licensePlate = ""; public float maxVel public void start(); public void stop(); default void blowHorn(){ System.out.println("Blowing horn"); } }
A fenti felület két mezőt, két metódust és egy alapértelmezett metódust tartalmaz. Egyedül nem sok haszna van, de általában az Osztályokkal együtt használják őket. Hogyan? Egyszerű, meg kell győződnie arról, hogy valaki osztályozza implements
.
public class Car implements Vehicle { public void start() { System.out.println("starting engine..."); } public void stop() { System.out.println("stopping engine..."); } }
Most van egy alapszabály : Az osztálynak meg kell valósítania az interfész összes metódusát. A metódusoknak pontosan ugyanazzal az aláírással kell rendelkezniük (név, paraméterek és kivételek), mint amit a felületen leírtak. Az osztálynak nem kell deklarálnia a mezőket, csak a metódusokat.
Interfész példányai
Miután létrehozott egy Java osztályt, amely implements
bármely interfész, az objektumpéldány hivatkozhat az interfész példányára. Ez a koncepció hasonló az öröklődés példányosításához.
// following our previous example Vehicle tesla = new Car(); tesla.start(); // starting engine ...
Az interfész nem tartalmazhat konstruktor módszereket. Ezért nem hozhat létre magának az interfésznek egy példányát. Létre kell hoznia egy osztály példányát, amely egy interfészt valósít meg a hivatkozás céljából.
Az interfészeket tekintse üres szerződés formának vagy sablonnak.
Mit tehet ezzel a funkcióval? Polimorfizmus! Csak interfészeket használhat objektum példányok hivatkozására!
class Truck implements Vehicle { public void start() { System.out.println("starting truck engine..."); } public void stop() { System.out.println("stopping truck engine..."); } } class Starter { // static method, can be called without instantiating the class public static void startEngine(Vehicle vehicle) { vehicle.start(); } } Vehicle tesla = new Car(); Vehicle tata = new Truck(); Starter.startEngine(tesla); // starting engine ... Starter.startEngine(tata); // starting truck engine ...
De mit szólnál több interfészhez?
Igen, egyetlen osztályban több interfészt is megvalósíthat. Míg az Osztályokon belüli öröklésben csak egy osztályt örökölhetsz, itt tetszőleges számú interfészt bővíthetsz. De ne felejtsük el, hogy végre minden a módszer az összes interfészek, különben összeállítása sikertelen lesz!
public interface GPS { public void getCoordinates(); } public interface Radio { public void startRadio(); public void stopRadio(); } public class Smartphone implements GPS,Radio { public void getCoordinates() { // return some coordinates } public void startRadio() { // start Radio } public void stopRadio() { // stop Radio } }
Az interfészek néhány szolgáltatása
- Változókat elhelyezhet az interfészen belül, bár ez nem lesz ésszerű döntés, mivel az osztályok nem kötelesek azonos változóval rendelkezni. Röviden, kerülje a változók elhelyezését!
- Az interfész összes változója és metódusa nyilvános, még akkor is, ha elhagyja a
public
kulcsszót. - Az interfész nem határozhatja meg egy adott módszer megvalósítását. Az osztályok feladata, hogy megcsinálja. Bár nemrégiben volt kivétel (lásd alább).
- Ha egy osztály több interfészt valósít meg, akkor távoli esélye van a metódus aláírás átfedésének. Mivel a Java nem engedélyezi az azonos aláírás több módszerét, ez problémákhoz vezethet. További információkért lásd ezt a kérdést.
Interfész alapértelmezett módszerei
A Java 8 előtt nem volt módunk arra, hogy irányítsunk egy interfészt egy adott módszer megvalósításához. Ez sok zavart és kódtörést eredményez, ha az interfész definícióját hirtelen megváltoztatják.
Tegyük fel, hogy írt egy nyílt forráskódú könyvtárat, amely tartalmaz egy interfészt. Tegyük fel, hogy az ügyfelek, azaz gyakorlatilag az összes fejlesztő a világ minden táján sokat használják és boldogok. Most frissítenie kellett a könyvtárat úgy, hogy új metódusdefiníciót adott hozzá az interfészhez egy új szolgáltatás támogatásához. De ez megszakítana minden felépítést, mivel az összes interfészt megvalósító osztálynak most meg kell változnia. Micsoda katasztrófa!
Szerencsére a Java 8 most default
módszert biztosít számunkra az interfészek számára. A default
módszer lehet tartalmazhat saját végrehajtását közvetlenül a felület! Tehát, ha egy osztály nem valósít meg alapértelmezett módszert, a fordító átveszi az interfészen belül említett megvalósítást. Szép, nem? Tehát a könyvtárában tetszőleges számú alapértelmezett metódust adhat hozzá az interfészekhez anélkül, hogy félne attól, hogy bármit is megtörne!
public interface GPS { public void getCoordinates(); default public void getRoughCoordinates() { // implementation to return coordinates from rough sources // such as wifi & mobile System.out.println("Fetching rough coordinates..."); } } public interface Radio { public void startRadio(); public void stopRadio(); } public class Smartphone implements GPS,Radio { public void getCoordinates() { // return some coordinates } public void startRadio() { // start Radio } public void stopRadio() { // stop Radio } // no implementation of getRoughCoordinates() } Smartphone motoG = new Smartphone(); motog.getRoughCoordinates(); // Fetching rough coordinates...
De mi történik, ha két interfész azonos metódus-aláírással rendelkezik?
Félelmetes kérdés. Ebben az esetben, ha nem biztosítja a megvalósítást az Osztályban, akkor a gyenge fordító összezavarodik és egyszerűen kudarcot vall! Az osztályon belül meg kell adnia egy alapértelmezett módszer-implementációt is. Van egy remek módja annak is, super
hogy melyik megvalósítást hívja meg:
public interface Radio { // public void startRadio(); // public void stopRadio(); default public void next() { System.out.println("Next from Radio"); } } public interface MusicPlayer { // public void start(); // public void pause(); // public void stop(); default public void next() { System.out.println("Next from MusicPlayer"); } } public class Smartphone implements Radio, MusicPlayer { public void next() { // Suppose you want to call MusicPlayer next MusicPlayer.super.next(); } } Smartphone motoG = new Smartphone(); motoG.next(); // Next from MusicPlayer
Statikus módszerek az interfészekben
A Java 8 újdonsága, hogy statikus módszereket adhat az interfészekhez. Az interfészek statikus módszerei szinte megegyeznek a konkrét osztályok statikus módszereivel. Az egyetlen nagy különbség az, hogy a static
metódusok nem öröklődnek az interfészt megvalósító osztályokban. Ez azt jelenti, hogy az interfészre hivatkozunk, amikor a statikus metódust hívjuk meg, nem pedig az osztályt, amely azt megvalósítja.
interface MusicPlayer { public static void commercial(String sponsor) { System.out.println("Now for a message brought to you by " + sponsor); } public void play(); } class Smartphone implements MusicPlayer { public void play() { System.out.println("Playing from smartphone"); } } class Main { public static void main(String[] args) { Smartphone motoG = new Smartphone(); MusicPlayer.commercial("Motorola"); // Called on interface not on implementing class // motoG.commercial("Motorola"); // This would cause a compilation error } }
Interfész öröklése
Az is lehetséges, hogy a Java-ban egy interfész egy másik interfészt örökölhet , a extends
kulcsszó használatával, kitalálta :
public interface Player { public void start(); public void pause(); public void stop(); } public interface MusicPlayer extends Player { default public void next() { System.out.println("Next from MusicPlayer"); } }
Ez azt jelenti, hogy az osztályt megvalósító MusicPlayer
interfésznek minden módszert meg kell valósítania MusicPlayer
, valamint Player
:
public class SmartPhone implements MusicPlayer { public void start() { System.out.println("start"); } public void stop() { System.out.println("stop"); } public void pause() { System.out.println("pause"); } }
Tehát most már jól ismeri a Java interfészeket! Tájékozódjon az Absztrakt osztályokról, és nézze meg, hogy a Java hogyan ad még egy módszert a szerződések meghatározására.