Что такое функциональный интерфейс

Ответ

Функциональный интерфейс — это интерфейс с одним абстрактным методом (SAM — Single Abstract Method). Он может содержать дефолтные или статические методы, но должен иметь только один нереализованный метод. Используется в лямбда-выражениях и ссылках на методы.

Пример в Kotlin:

fun interface OnClickListener {
    fun onClick(view: View)
}

// Использование:
val listener = OnClickListener { view -> 
    println("Clicked!")
}

В Java аннотация @FunctionalInterface явно указывает на такое назначение интерфейса, хотя и не обязательна. Примеры: Runnable, Comparator, Consumer.

Ответ 18+ 🔞

Э, слушай, а вот этот ваш функциональный интерфейс — это вообще хитрая жопа, но на самом деле всё просто, как ёб твою мать. Представь себе обычный интерфейс, но такой, который заточен под одну конкретную операцию. Как будто ты говоришь: «Слушай, чувак, мне нужен инструмент, который делает вот это одно действие, и всё». И всё, блядь, на этом философия заканчивается.

По-умному это называется SAM — Single Abstract Method. То есть в этом интерфейсе должен быть ровно один абстрактный метод, который ты обязан реализовать. А вот дефолтных методов или статических — можешь навешать овердохуища, это не запрещено. Главное, чтобы этот один-единственный священный абстрактный метод был. Он и есть вся суть.

Зачем это надо? Ну, ёпта, для красоты и лаконичности, в основном. Вся эта мода на лямбды и ссылки на методы пошла. Вместо того чтобы городить анонимный класс на три экрана, ты пишешь одну строчку. Удобно же, правда?

Вот смотри, как в Kotlin это выглядит, прям наглядно:

fun interface OnClickListener {
    fun onClick(view: View)
}

// Использование:
val listener = OnClickListener { view -> 
    println("Clicked!")
}

Видишь? Объявили интерфейс с ключевым словом fun — и всё, он теперь функциональный. А когда создаёшь объект, просто пишешь лямбду в фигурных скобках. Красота, ядрёна вошь! Никакого лишнего бойлерплейта, чистая магия.

В Java, кстати, тоже есть такая фишка, но там немного иначе. Там можно любой интерфейс с одним методом использовать как функциональный, но умные дядьки придумали аннотацию @FunctionalInterface. Её ставить не обязательно, но она как бы говорит компилятору: «Чувак, я тут задумал функциональный интерфейс, так что смотри, чтобы я случайно не добавил второй абстрактный метод, а то будет пиздец». То есть это такая защита от самого себя, от кривых рук.

Самые известные примеры, которые все видели, даже если не знали, что они функциональные — это Runnable (у него метод run()), Comparator (метод compare()), или Consumer (метод accept()). Они все под эту гребёнку попадают.

Короче, суть в чём: один метод — одна ответственность. Не надо распыляться, не надо делать интерфейс, который пытается быть всем для всех. Сделал одну штуку — и молодец. Как говорится, доверия ебать ноль к многостаночникам, а тут всё прозрачно.

Видео-ответы