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 enumsa Java 5 előtt.
Alapértelmezett metódusok az interfészekben - 1
É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:

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 aUnusualCarosztá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 {
}
FlyingBirdEnnek megfelelően az öröklődő madarakat a madárházba küldjük , míg az abból származó madarakat Waterfowla 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! :)