Різниця між класом Abstact та інтерфейсом
- Абстрактні класи проти інтерфейсів на Java 8
- Концептуальна різниця:
Методи інтерфейсу за замовчуванням на Java 8
- Що таке метод за замовчуванням?
- Помилка компіляції методу ForEach вирішена за допомогою методу за замовчуванням
- Метод за замовчуванням і багатозначні проблеми з неоднозначністю успадкування
- Важливі моменти щодо стандартних методів інтерфейсу Java:
Статичний метод інтерфейсу Java
- Статичний метод інтерфейсу Java, приклад коду, статичний метод проти метод за замовчуванням
- Важливі моменти статичного методу інтерфейсу Java:
Функціональні інтерфейси Java
Абстрактні класи проти інтерфейсів на Java 8
Зміни інтерфейсу Java 8 включають статичні методи та методи за замовчуванням в інтерфейсах. До Java 8 ми могли мати лише інтерпретації методів в інтерфейсах. Але з Java 8 ми можемо мати методи за замовчуванням та статичні методи в інтерфейсах.
Після введення методу за замовчуванням здається, що інтерфейси та абстрактні класи однакові. Однак вони все ще відрізняються концепцією в Java 8.
Абстрактний клас може визначати конструктор. Вони більш структуровані і можуть мати стан, пов'язаний з ними. На відміну від цього, метод за замовчуванням може бути реалізований лише в умовах виклику інших методів інтерфейсу, без посилання на стан конкретної реалізації. Отже, і використання в різних цілях, і вибір між двома дійсно залежить від контексту сценарію.
Концептуальна різниця:
Абстрактні класи дійсні для скелетних (тобто часткових) реалізацій інтерфейсів, але не повинні існувати без відповідного інтерфейсу.
Отже, коли абстрактні класи ефективно зводяться до низької видимості, скелетних реалізацій інтерфейсів, чи можуть методи за замовчуванням і це забрати? Рішуче: Ні! Реалізація інтерфейсів майже завжди вимагає деяких або всіх тих інструментів побудови класів, у яких відсутні методи за замовчуванням. І якщо якийсь інтерфейс цього не робить, це, очевидно, особливий випадок, який не повинен вас збивати з шляху.
Методи інтерфейсу за замовчуванням на Java 8
Java 8 вводить нову функцію « Метод за замовчуванням » або (Методи Defender), яка дозволяє розробнику додавати нові методи в Інтерфейси, не порушуючи існуючої реалізації цього Інтерфейсу. Це забезпечує гнучкість, що дозволяє інтерфейсу визначити реалізацію, яка буде використовуватись за замовчуванням у ситуації, коли конкретний клас не може забезпечити реалізацію цього методу.
Розглянемо невеликий приклад, щоб зрозуміти, як це працює:
public interface OldInterface {
public void existingMethod();
default public void newDefaultMethod() {
System.out.println("New default method"
+ " is added in interface");
}
}
Наступний клас успішно складеться в Java JDK 8,
public class OldInterfaceImpl implements OldInterface {
public void existingMethod() {
// existing implementation is here…
}
}
Якщо ви створюєте екземпляр OldInterfaceImpl:
OldInterfaceImpl obj = new OldInterfaceImpl ();
// print “New default method add in interface”
obj.newDefaultMethod();
Методи за замовчуванням ніколи не є остаточними, не можуть бути синхронізовані і не можуть замінити методи Об'єкта. Вони завжди публічні, що сильно обмежує можливість писати короткі та багаторазові методи.
Методи за замовчуванням можуть бути надані інтерфейсу, не впливаючи на реалізацію Класів, оскільки вона включає реалізацію. Якщо кожен доданий метод в інтерфейсі, визначеному реалізацією, не впливає жоден клас реалізації. Клас, що реалізує, може замінити реалізацію за замовчуванням, надану інтерфейсом.
Методи за замовчуванням дозволяють додати нову функціональність до існуючих інтерфейсів, не порушуючи старішої реалізації цих інтерфейсів.
Коли ми розширюємо інтерфейс, який містить метод за замовчуванням, ми можемо виконувати наступні,
- Не змінюватиме метод за замовчуванням і успадковуватиме метод за замовчуванням.
- Замініть метод за замовчуванням, подібний до інших методів, які ми перекриваємо в підкласі.
- Перевизначити метод за замовчуванням як абстрактний, який змушує підклас переосмислювати його.
Помилка компіляції методу ForEach вирішена за допомогою методу за замовчуванням
Для Java 8 колекції JDK були розширені, і до всієї колекції додається метод forEach (які працюють в поєднанні з лямбдами). Звичайним способом код виглядає нижче,
public interface Iterable<T> {
public void forEach(Consumer<? super T> consumer);
}
Оскільки це результат кожного класу реалізації з помилками компіляції, таким чином, додається метод за замовчуванням з необхідною реалізацією для того, щоб існуюча реалізація не повинна бути змінена.
Інтерактивний інтерфейс із методом за замовчуванням знаходиться нижче,
public interface Iterable<T> {
public default void forEach(Consumer
<? super T> consumer) {
for (T t : this) {
consumer.accept(t);
}
}
}
Цей же механізм був використаний для додавання потоку в інтерфейс JDK, не порушуючи класи реалізації.
Метод за замовчуванням і багатозначні проблеми з неоднозначністю успадкування
Оскільки java Class може реалізувати декілька інтерфейсів, і кожен інтерфейс може визначити метод за замовчуванням з однаковим підписом методу, отже, успадковані методи можуть конфліктувати один з одним.
Розглянемо нижче приклад,
public interface InterfaceA {
default void defaultMethod(){
System.out.println("Interface A default method");
}
}
public interface InterfaceB {
default void defaultMethod(){
System.out.println("Interface B default method");
}
}
public class Impl implements InterfaceA, InterfaceB {
}
Вищевказаний код не вдасться скомпілювати із такою помилкою,
java: клас Impl успадковує незв'язані параметри за замовчуванням для defaultMethod () від типів InterfaceA та InterfaceB
Для виправлення цього класу нам потрібно надати реалізацію методу за замовчуванням:
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
}
}
Далі, якщо ми хочемо посилатися на реалізацію за замовчуванням, яку надає будь-який суперінтерфейс, а не власна реалізація, ми можемо зробити це наступним чином,
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
// existing code here..
InterfaceA.super.defaultMethod();
}
}
Ми можемо вибрати будь-яку реалізацію за замовчуванням або обидві як частину нашого нового методу.
Важливі моменти щодо стандартних методів інтерфейсу Java:
- Методи за замовчуванням інтерфейсу Java допоможуть нам розширити інтерфейси, не боячись порушити класи реалізації.
- Методи за замовчуванням інтерфейсу Java дозволяють зменшити відмінності між інтерфейсами та абстрактними класами.
- Методи за замовчуванням інтерфейсу Java 8 допоможуть нам уникнути класів утиліти, наприклад, всі методи класу Collections можуть бути надані в самих інтерфейсах.
- Методи за замовчуванням інтерфейсу Java допоможуть нам у видаленні базових класів реалізації, ми можемо забезпечити реалізацію за замовчуванням, а класи реалізації можуть вибрати, який з них переотримати.
- Однією з головних причин введення методів за замовчуванням в інтерфейси є вдосконалення API Collections в Java 8 для підтримки лямбда-виразів.
- Якщо будь-який клас в ієрархії має метод з однаковою підписом, то методи за замовчуванням стають неактуальними. Метод за замовчуванням не може замінити метод з java.lang.Object. Міркування дуже просте, тому що Object є базовим класом для всіх класів java. Тож навіть якщо у нас інтерфейси методів класу Object визначені як методи за замовчуванням в інтерфейсах, вони будуть марні, оскільки завжди буде використовуватися метод класу Object. Тому, щоб уникнути плутанини, у нас не може бути методів за замовчуванням, які переважають методи класу Object.
- Методи за замовчуванням інтерфейсу Java також називаються методами Defender або методами віртуального розширення.
Посилання на ресурс:
- Інтерфейс із методами за замовчуванням та класом Анотація на Java 8
- Абстрактний клас проти інтерфейсу в епоху JDK 8
- Еволюція інтерфейсу за допомогою методів віртуального розширення
Статичний метод інтерфейсу Java
Статичний метод інтерфейсу Java, приклад коду, статичний метод проти метод за замовчуванням
Статичний метод інтерфейсу Java схожий на метод за замовчуванням, за винятком того, що ми не можемо їх замінити в класах реалізації. Ця функція допомагає нам уникнути небажаних результатів у разі поганої реалізації у класах впровадження. Давайте розглянемо це на простому прикладі.
public interface MyData {
default void print(String str) {
if (!isNull(str))
System.out.println("MyData Print::" + str);
}
static boolean isNull(String str) {
System.out.println("Interface Null Check");
return str == null ? true : "".equals(str) ? true : false;
}
}
Тепер давайте подивимось клас реалізації, який має метод isNull () з поганою реалізацією.
public class MyDataImpl implements MyData {
public boolean isNull(String str) {
System.out.println("Impl Null Check");
return str == null ? true : false;
}
public static void main(String args[]){
MyDataImpl obj = new MyDataImpl();
obj.print("");
obj.isNull("abc");
}
}
Зауважте, що isNull (String str) - це простий метод класу, він не переосмислює метод інтерфейсу. Наприклад, якщо ми додамо анотацію @Override до методу isNull (), це призведе до помилки компілятора.
Тепер, коли ми запустимо додаток, ми отримаємо наступний вихід.
Інтерфейс нульової перевірки
Impl Null Check
Якщо ми перетворимо метод інтерфейсу від статичного до типового, ми отримаємо наступний вихід.
Impl Null Check
MyData Друк ::
Impl Null Check
Статичний метод інтерфейсу Java видимий лише для методів інтерфейсу, якщо ми видалимо метод isNull () з класу MyDataImpl, ми не зможемо використовувати його для об’єкта MyDataImpl. Однак, як і інші статичні методи, ми можемо використовувати статичні методи інтерфейсу за допомогою назви класу. Наприклад, дійсною заявою буде:
boolean result = MyData.isNull("abc");
Важливі моменти статичного методу інтерфейсу Java:
- Статичний метод інтерфейсу Java є частиною інтерфейсу, ми не можемо використовувати його для об’єктів класу реалізації.
- Статичні методи інтерфейсу Java хороші для надання корисних методів, наприклад, перевірки нуля, сортування колекції тощо.
- Статичний метод інтерфейсу Java допомагає нам у забезпеченні безпеки, не дозволяючи класам впровадження їх замінювати.
- Ми не можемо визначити статичний метод інтерфейсу для методів класу Object, ми отримаємо помилку компілятора як "Цей статичний метод не може приховати метод примірника від Object". Це тому, що в Java не дозволено, оскільки Object є базовим класом для всіх класів, і ми не можемо стати статичним методом рівня одного класу та іншим методом екземпляра з однаковою підписом.
- Ми можемо використовувати статичні методи інтерфейсу Java для видалення класів утиліт, таких як Collections, і перемістити всі його статичні методи у відповідний інтерфейс, який було б легко знайти та використовувати.
Функціональні інтерфейси Java
Перш ніж я закінчу повідомлення, я хотів би коротко ознайомитись з функціональними інтерфейсами. Інтерфейс з точно одним абстрактним методом відомий як функціональний інтерфейс.
@FunctionalInterface
Було введено нову примітку для позначення інтерфейсу як функціонального інтерфейсу. @FunctionalInterface
анотація - це можливість уникнути випадкового додавання абстрактних методів у функціональні інтерфейси. Це необов’язково, але хороша практика використовувати його.
Функціональні інтерфейси довгоочікувані і дуже затребувані особливості Java 8, оскільки це дозволяє нам використовувати лямбда-вирази для їх інстанції. Новий пакет java.util.function з купою функціональних інтерфейсів додається для забезпечення цільових типів лямбда-виразів та посилань на методи. Ми розглянемо функціональні інтерфейси та лямбда-вирази в майбутніх публікаціях.
Розташування ресурсу:
- Зміни інтерфейсу Java 8 - статичний метод, метод за замовчуванням