Всяка нова version на Java се различава от предишните. Като пример за такава промяна от материала, който покрихме, езикът не е имал enumsпреди Java 5.
Методи по подразбиране в интерфейсите - 1
Точно така, Java 8 е забележимо различна от Java 7. Разбира се, няма да пренебрегнем важни нововъведения. Тъй като в този урок говорим за интерфейси, нека разгледаме една актуализация на езика: методи по подразбиране в интерфейси . Вече знаете, че интерфейсът не прилага поведение . Целта му е да опише Howво поведение трябва да съществува във всички обекти, които имплементират интерфейса . Но разработчиците често се сблъскват със ситуации, при които внедряването на даден метод е еднакво във всички класове. Нека да разгледаме нашия пример със стара кола:

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!");
   }
}
Какъв според вас е основният проблем с този code? Вероятно сте забелязали, че написахме куп дублиран code! Това е често срещан проблем при програмирането и трябва да се избягва. Друг е въпросът, че нямаше конкретни решения преди пускането на Java 8. Когато тази version излезе, стана възможно да се дефинират методи по подразбиране и да се внедрят направо в интерфейс! Ето How да го направите:

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 {

}
Сега методите gas()и brake(), които бяха еднакви за всички автомобor, бяха преместени в интерфейса, елиминирайки необходимостта от дублиран code. И методите са налични във всеки един от класовете!

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();
   }
}
Ами ако има 100 класа с gas()метод, но само 99 от тях трябва да имат същото поведение? Това разваля ли всичко? Методът по подразбиране няма ли да работи в този случай? Разбира се, че не :) Методите на интерфейса по подразбиране могат да бъдат заменени.

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!");
   }
}
Всички останали 99 типа автомобor ще използват метода по подразбиране, докатоUnusualCarклас е изключение. Без да разваля голямата картина, то спокойно ще определи собственото си поведение. Множествено наследяване в интерфейсите. Както вече знаете, в Java няма множествено наследяване. Има много причини за това. Ще ги разгледаме подробно в отделен урок. В други езици, като C++, ситуацията е обратна. Никое множествено наследяване не представлява сериозно предизвикателство, тъй като един и същ обект може да има няколко различни характеристики и поведение. Например, ние сме деца за нашите родители, ученици за нашите учители и пациенти за нашите лекари. В реалния живот изпълняваме различни роли и съответно се държим по различен начин: очевидно взаимодействаме с учителите по различен начин, отколкото с близки приятели. Нека се опитаме да преведем тази ситуация в code. Нека си представим, че имаме два класа: езерце и волиера. Езерото се нуждае от плуващи птици, докато волиерата се нуждае от летящи. За да представим това, създадохме два базови класа:FlyingBirdи Waterfowl.

public class Waterfowl {
}

public class FlyingBird {
}
Съответно, ние ще изпратим птици, които наследяват FlyingBirdвъв волиерата, докато тези, които произлизат от, Waterfowlще отидат в езерото. Всичко изглежда просто. Но Howво трябва да направим, ако трябва да дефинираме патица някъде? Патиците и плуват, и летят. Но ние нямаме множествено наследяване. За щастие Java поддържа множество реализации на интерфейси. Ако един клас не може да наследява множество родители, прилагането на множество интерфейси е лесно! Нашата патица може да бъде Howто летяща, така и плуваща птица :) За да постигнем желания резултат, всичко, което трябва да направим, е да създадем FlyingBirdинтерфейси, 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!");
   }
}
Това означава, че нашата програма запазва възможността за гъвкаво управление на класовете. Когато комбинираме това с методите по подразбиране, способността ни да определяме поведението на обектите става почти неограничена! :)