Proszę nie trollować za bardzo, dopiero zaczynam tłumaczyć artykuły
Interfejs może dziedziczyć z innego interfejsu; jeśli interfejs dziedziczy z interfejsu funkcjonalnego i nie zawiera nowych metod abstrakcyjnych, to ten interfejs również jest funkcjonalny. Jednak interfejs może zawierać tylko jedną metodę abstrakcyjną i wiele metod domyślnych i nadal będzie uważany za funkcjonalny.
Wprowadzenie do interfejsów funkcjonalnych — koncepcje odtworzone w Javie 8
Każdy programista Java na świecie choć raz użył jednego z następujących interfejsów:java.lang.Runnable
, java.awt.event.ActionListener
, java.util.Comparator
, java.util.concurrent.Callable
. Wszystkie mają jedną wspólną cechę, a mianowicie to, że wszystkie mają tylko jedną metodę. W JDK istnieje wiele innych takich interfejsów, a także inne stworzone przez programistów Java. Interfejsy te są również znane jako Single Abstract Method interfaces
(interfejsy SAM). Jednym z najpopularniejszych sposobów wykorzystania tych interfejsów jest tworzenie anonimowych klas wewnętrznych, które korzystają z tych interfejsów, jak w poniższym przykładzie:
public class AnonymousInnerClassTest {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("A thread created and running...");
}
}).start();
}
}
W Javie 8 koncepcja SAM została odtworzona i nazwana interfejsami funkcjonalnymi. Można je reprezentować za pomocą wyrażeń lambda, odwołań do metod i konstruktorów referencyjnych. Utworzono nową adnotację @FunctionalInterface, która służy do zgłaszania błędów na poziomie kompilatora, gdy interfejs, który zanotowałeś, nie działa na poziomie funkcjonalnym. Przyjrzyjmy się prostemu interfejsowi funkcjonalnemu z jedną abstrakcyjną metodą:
@FunctionalInterface
public interface SimpleFunInterface {
public void doWork();
}
Interfejs może również deklarować metody abstrakcyjne z klasy java.lang.Object
, ale w tym przypadku interfejs można również zadeklarować jako funkcjonalny:
@FunctionalInterface
public interface SimpleFuncInterface {
public void doWork();
public String toString();
public Boolean equals(Object o);
}
Gdy tylko dodasz do interfejsu kolejną metodę abstrakcyjną, IDE oznaczy ją jako błędną jak na obrazku:
Co jeszcze warto przeczytać: |
---|
@FunctionalInterface
public interface ComplexFunctionalInterface extends SimpleFuncInterface {
default public void doSomeWork() {
System.out.println("Doing some work in interface impl...");
}
default public void doSomeWork() {
System.out.println("Doing some other work in interface impl...");
}
}
Najlepszym przykładem jest nadal funkcjonalny interfejs. Przyjrzyjmy się teraz, jak możemy użyć wyrażeń lambda do zastąpienia anonimowej klasy wewnętrznej w celu zaimplementowania interfejsów funkcjonalnych:
/*
*Implementation the interface by creating an
*anonymoous inner class versus using
*lambda expression.
*/
public class SimpleFunInterfaceTest {
public static void main(String[] args) {
carryOutWork(new SimpleFunInterface() {
@Override
public void doWork() {
System.out.println("Do work in SimpleFun impl...");
}
});
carryOutWork(() -> System.out.println("Do work in lambda exp impl..."));
}
public static void carryOutWork(SimpleFuncInterface sfi) {
sfi.work();
}
}
Wynik programu będzie następujący:
Do work in SimpleFun impl...
Do work in lambda exp impl...
Jeśli używasz IDE obsługującego składnię wyrażeń lambda w Javie (kompilacje Netbeans 8 Nightly) – otrzymasz podpowiedź podczas korzystania z anonimowych klas wewnętrznych: To było krótkie wprowadzenie do koncepcji interfejsów funkcjonalnych w Javie 8 i tego, jak można je zaimplementować za pomocą wyrażeń lambda.
GO TO FULL VERSION