CodeGym /Kurslar /JAVA 25 SELF /Funksional interfeyslər: @FunctionalInterface

Funksional interfeyslər: @FunctionalInterface

JAVA 25 SELF
Səviyyə, Dərs
Mövcuddur

1. Giriş

Funksional interfeys — tərkibində məhz bir abstrakt metod olan (yəni reallaşdırması olmayan metod) interfeysdir. Məhz belə interfeys metodun reallaşdırılmasını yığcam yazmaq üçün istifadə olunur — Java-da bu, lambda ifadələri vasitəsilə edilir (onları sonra öyrənəcəyik).

Niyə yalnız bir metod?

Çünki funksional interfeys məhz bir əməliyyatı təsvir edir. Əgər metodlar iki və ya daha çox olsaydı, hansı metodun reallaşdırılmalı olduğu aydın olmazdı. Buna görə qayda sadədir: bir interfeys — bir abstrakt metod.

Standart kitabxanadan nümunələr

  • Runnable — axınlarda tapşırıqlar üçün (void run())
  • Callable<V> — nəticə qaytaran tapşırıqlar üçün (V call())
  • Comparator<T> — obyektləri müqayisə etmək üçün (int compare(T o1, T o2))
  • Consumer<T> — dəyərin “istehlakçısı” (void accept(T t))
  • Supplier<T> — dəyərin “təchizatçısı” (T get())
  • Function<T, R> — T-dən R-ə funksiya (R apply(T t))
  • Predicate<T> — şərtin yoxlanması (boolean test(T t))

Məsələn, Runnable interfeysi:

public interface Runnable {
    void run();
}

Və budur, Comparator interfeysi:

public interface Comparator<T> {
    int compare(T o1, T o2);
    // ... başqa default və static metodlar da var, amma abstrakt metod cəmi birdir!
}

Vacib məqam: default və static metodlar abstrakt sayılmır, buna görə də onlardan istədiyiniz qədər ola bilər!

2. Annotasiya @FunctionalInterface

Java — sərt və prinsipial bir xanımdır. Qarışıqlıq olmasın deyə, interfeysi açıq şəkildə funksional kimi @FunctionalInterface annotasiyası ilə işarələməyə imkan verir. Bu, “Yalnız bir düymə ilə işləyir!” stikerinə bənzəyir — kimsə artıq nəsə əlavə etməsin deyə.

@FunctionalInterface
public interface Operation {
    int apply(int a, int b);
}

İndi, əgər birdən-birə unudub ikinci abstrakt metod əlavə etsəniz, kompilyator dərhal xəta barədə xəbər verəcək:

@FunctionalInterface
public interface Oops {
    void doIt();
    void doSomethingElse(); // Səhv! İki abstrakt metod
}

Annotasiya mütləqdirmi?

Xeyr, məcburi deyil. İnterfeys məhz bir abstrakt metoddan ibarətdirsə, o, onsuz da funksional olacaq. Lakin annotasiya ilə niyyətinizi açıq göstərir və özünüzü təsadüfi səhvlərdən qoruyursunuz.

default və static metodları əlavə etmək olarmı?

Bəli, olar! Əsas odur ki, yalnız bir abstrakt metod olsun. Qalan bütün metodlar istədiyiniz qədər default və ya static ola bilər.

Nümunə:

@FunctionalInterface
public interface FancyOperation {
    int apply(int a, int b);

    default void printInfo() {
        System.out.println("Mən — fancy əməliyyatam!");
    }

    static void description() {
        System.out.println("Arifmetika üçün funksional interfeys.");
    }
}

3. Elan və istifadə nümunələri

Tutaq ki, iki ədəd üzərində əməliyyatı təsvir etmək istəyirsiniz. Bu, belə edilir:

@FunctionalInterface
public interface Operation {
    int apply(int a, int b);
}

İndi bu interfeysi müxtəlif cür reallaşdırmaq olar.

Adi sinif vasitəsilə reallaşdırma

public class SumOperation implements Operation {
    @Override
    public int apply(int a, int b) {
        return a + b;
    }
}

İstifadə:

Operation sum = new SumOperation();
System.out.println(sum.apply(2, 3)); // 5

Anonim sinif vasitəsilə reallaşdırma

Operation multiply = new Operation() {
    @Override
    public int apply(int a, int b) {
        return a * b;
    }
};
System.out.println(multiply.apply(2, 3)); // 6

Lambdalar barədə qeyd

Java 8-dən başlayaraq bu cür interfeysləri lambda ifadələri — daha qısa sintaksis — ilə rahat reallaşdırmaq olur. Lambdaları bir neçə dərsdən sonra öyrənəcəyik, buna görə hələlik bilmək kifayətdir: funksional interfeyslər məhz onlarla maksimal rahat işləmək üçün yaradılıb.

4. Təcrübə: öz funksional interfeysini yaz

Tapşırıq 1. Öz Action-unuzu yaradın!

Sətir qəbul edən və heç nə qaytarmayan Action interfeysi yaradın. Onu sətiri böyük hərflərlə çap edən anonim sinif vasitəsilə reallaşdırın.

@FunctionalInterface
interface Action {
    void act(String s);
}

public class ActionDemo {
    public static void main(String[] args) {
        Action shout = new Action() {
            @Override
            public void act(String text) {
                System.out.println(text.toUpperCase());
            }
        };

        shout.act("mən java öyrənirəm!"); // MƏN JAVA ÖYRƏNİRƏM!
    }
}

(Sonradan bunu lambda ifadələri ilə daha qısa yazmağın mümkün olduğunu görəcəyik.)

Tapşırıq 2. Ədədlərin filtri

NumberPredicate interfeysini boolean test(int n) metodu ilə yaradın. Cüt olma yoxlamasını anonim sinif vasitəsilə reallaşdırın.

@FunctionalInterface
interface NumberPredicate {
    boolean test(int n);
}

public class PredicateDemo {
    public static void main(String[] args) {
        NumberPredicate isEven = new NumberPredicate() {
            @Override
            public boolean test(int n) {
                return n % 2 == 0;
            }
        };

        System.out.println(isEven.test(4)); // true
        System.out.println(isEven.test(7)); // false
    }
}

Tapşırıq 3. Standart interfeyslərdən istifadə

Öz interfeysiniz əvəzinə hazır Predicate<Integer>-dən istifadə etmək olar:

import java.util.function.Predicate;

Predicate<Integer> isPositive = new Predicate<Integer>() {
    @Override
    public boolean test(Integer x) {
        return x > 0;
    }
};

System.out.println(isPositive.test(10)); // true
System.out.println(isPositive.test(-5)); // false

Cədvəl: standart kitabxanadakı funksional interfeyslər

İnterfeys Metod Təsvir Tətbiq nümunəsi
Runnable
void run()
Arqumentsiz və nəticəsiz tapşırıq Axınlar, taymerlər
Callable<V>
V call()
Nəticəli tapşırıq Axınlar, ExecutorService
Comparator<T>
int compare(T, T)
İki obyektin müqayisəsi Kolleksiyaların sıralanması
Consumer<T>
void accept(T)
Dəyərin “istehlakçısı” Kolleksiya üzərində iterasiya
Supplier<T>
T get()
Dəyərin “təchizatçısı” Tənbəl inisializasiya, məlumatların yaradılması
Function<T, R>
R apply(T)
T-dən R-ə funksiya Məlumatların çevrilməsi
Predicate<T>
boolean test(T)
Şərtin yoxlanması Kolleksiyaların filtrasiyası

5. Funksional interfeyslərlə işləyərkən tipik səhvlər

Səhv №1: ikinci abstrakt metod əlavə olunub. Əgər interfeys bir neçə abstrakt metoddan ibarətdirsə, o, artıq funksional deyil. Kompilyator (xüsusən də @FunctionalInterface ilə) dərhal xəta barədə xəbər verəcək.

Səhv №2: default və static metodların abstrakt sayılmadığını unutmusunuz. Onları funksional interfeysə rahatlıqla əlavə edə bilərsiniz — bu, “bir abstrakt metod” qaydasını pozmur.

Səhv №3: metodun siqnatürasını səhv reallaşdırmısınız. Məsələn, interfeys iki arqument tələb edir, siz isə metodu yalnız bir arqumentlə yazmısınız. Həmişə siqnaturaları yoxlayın.

Səhv №4: @FunctionalInterface-dən istifadə etmirsiniz və interfeysi təsadüfən korlayırsınız. İnterfeysi annotasiya ilə işarələməsəniz, təsadüfən artıq metod əlavə edə bilərsiniz — sonra isə niyə kodun işləmədiyini uzun müddət axtararsınız. Daha yaxşısı, həmişə niyyəti açıq göstərmək üçün annotasiyanı əlavə edin.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Sizin Fərdi Bildirişiniz
Sizin Fərdi Bildirişiniz
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Oyun yoxlayıcısı: Yüksək xallar
Oyun yoxlayıcısı: Yüksək xallar
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Mətn Validatoru: Sətir Uzunluğunun Yoxlanması
Mətn Validatoru: Sətir Uzunluğunun Yoxlanması
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Mətn Konvertoru və Rahat Çıxış
Mətn Konvertoru və Rahat Çıxış
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION