A Java minden új verziója eltér a korábbiaktól. Az általunk tárgyalt anyag ilyen változásának példájaként a nyelv nem rendelkezett
Éppen ezért a Java 8 észrevehetően különbözik a Java 7-től. Természetesen a fontos újításokat sem hagyjuk figyelmen kívül. Mivel ebben a leckében interfészekről beszélünk, vegyünk egy frissítést a nyelvhez: alapértelmezett metódusok az interfészekben . Már tudja, hogy egy interfész nem valósítja meg a viselkedést . Célja, hogy leírja, milyen viselkedésnek kell lennie az interfészt megvalósító összes objektumban . De a fejlesztők gyakran találkoztak olyan helyzetekkel, amikor egy metódus megvalósítása minden osztályban azonos volt. Nézzük a régi autónk példáját:
enums
a Java 5 előtt.
![Alapértelmezett metódusok az interfészekben - 1](https://cdn.codegym.cc/images/article/6abd4f1b-c572-4810-8fa7-42ef025df602/512.jpeg)
public interface Car {
public void gas();
public void brake();
}
public class Sedan implements Car {
@Override
public void gas() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
public class Truck implements Car {
@Override
public void go() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
public class F1Car implements Car {
@Override
public void go() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
Szerinted mi a fő probléma ezzel a kóddal? Valószínűleg észrevetted, hogy egy csomó duplikált kódot írtunk! Ez gyakori probléma a programozásban, és ezt el kell kerülni. Más kérdés, hogy a Java 8 megjelenése előtt nem voltak konkrét megoldások. Amikor ez a verzió megjelent, lehetővé vált az alapértelmezett metódusok definiálása és implementálása közvetlenül egy felületen belül! Íme, hogyan kell csinálni:
public interface Car {
public default void gas() {
System.out.println("Gas!");
}
public default void brake() {
System.out.println("Brake!");
}
}
public class Sedan implements Car {
}
public class Truck implements Car {
}
public class F1Car implements Car {
}
Most az gas()
és brake()
metódusok, amelyek minden autónál azonosak voltak, átkerültek a felületre, így nincs szükség duplikált kódra. A módszerek pedig minden osztályban elérhetőek!
public class Main {
public static void main(String[] args) {
F1Car f1Car = new F1Car();
Sedan sedan = new Sedan();
Truck truck = new Truck();
truck.gas();
sedan.gas();
f1Car.brake();
}
}
Mi van akkor, ha 100 osztály rendelkezik egy gas()
metódussal, de közülük csak 99-nek kell ugyanazt a viselkedését? Ez mindent elront? Ebben az esetben egy alapértelmezett módszer nem működik? Természetesen nem :) Az alapértelmezett interfész metódusok felülbírálhatók.
public class UnusualCar implements Car {
@Override
public void go() {
System.out.println("This car accelerates differently!");
}
@Override
public void brake() {
System.out.println("This car slows down differently!");
}
}
Az összes többi 99 autótípus az alapértelmezett módszert fogja alkalmazni, míg aUnusualCar
osztály kivétel. Anélkül, hogy elrontaná az összképet, nyugodtan meghatározza saját viselkedését. Többszörös öröklődés az interfészekben. Mint már tudja, a Java-ban nincs többszörös öröklődés. Ennek számos oka van. Ezeket egy külön leckében részletesen megvizsgáljuk. Más nyelvekben, például a C++-ban, a helyzet fordított. A többszörös öröklődés hiánya komoly kihívást jelent, mivel ugyanaz az objektum többféle tulajdonsággal és viselkedéssel rendelkezhet. Például szüleink számára gyerekek vagyunk, tanáraink számára diákok, orvosaink számára betegek vagyunk. A való életben különféle szerepeket töltünk be, és ennek megfelelően eltérően viselkedünk: nyilvánvalóan másként lépünk kapcsolatba a tanárokkal, mint a közeli barátokkal. Próbáljuk meg ezt a helyzetet kódra fordítani. Képzeljük el, hogy két osztályunk van: Pond és Aviary. Egy tóban úszó madarak, míg egy madárházban repülő madarak kellenek. Ennek bemutatására két alaposztályt hoztunk létre:FlyingBird
és Waterfowl
.
public class Waterfowl {
}
public class FlyingBird {
}
FlyingBird
Ennek megfelelően az öröklődő madarakat a madárházba küldjük , míg az abból származó madarakat Waterfowl
a tóba küldjük. Minden egyértelműnek tűnik. De mit tegyünk, ha valahol meg kell határoznunk egy kacsát? A kacsák úsznak és repülnek is. De nincs többszörös örökségünk. Szerencsére a Java támogatja az interfészek többféle megvalósítását. Ha egy osztály nem örökölhet több szülőt, akkor több interfész megvalósítása egyszerű! A mi kacsánk lehet repülő és úszó madár is :) A kívánt eredmény eléréséhez nem kell mást tennünk, mint az osztályok helyett az interfészeket FlyingBird
és az interfészt készíteni.Waterfowl
public class Duck implements FlyingBird, Waterfowl {
// Methods of both interfaces combine easily into one class
@Override
public void fly() {
System.out.println("Flying!");
}
@Override
public void swim() {
System.out.println("Swimming!");
}
}
Ez azt jelenti, hogy programunk megtartja az osztályok rugalmas kezelésének lehetőségét. Ha ezt az alapértelmezett módszerekkel kombináljuk, az objektumok viselkedésének meghatározására való képességünk szinte korlátlanná válik! :)
GO TO FULL VERSION