•
추상 메서드가 하나만 있는 인터페이스를 함수형 인터페이스 또는 단일 추상 메서드(SAM) 인터페이스라고 한다.
•
함수형 인터페이스는 여러 개의 추상이 아닌 멤버를 가질 수 있지만 추상 멤버는 하나만 가질 수 있다.
•
함수형 인터페이스를 선언하려면 fun 수정자를 사용한다.
fun interface KRunnable {
fun invoke()
}
Kotlin
복사
SAM 변환
•
람다 표현식을 사용하여 코드를 더 간결하고 읽기 쉽게 만드는 SAM 변환을 사용할 수 있다.
•
함수형 인터페이스를 수동으로 구현하는 클래스를 만드는 대신 람다 표현식을 사용할 수 있다.
•
람다 표현식의 시그니처가 인터페이스의 단일 메서드 시그니처와 일치할 때 해당 인터페이스 구현을 동적으로 생성하는 코드로 변환할 수 있다.
// 함수형 인터페이스
fun interface IntPredicate {
fun accept(i: Int): Boolean
}
// SAM 변환을 사용하지 않은 경우
val isEven = object : IntPredicate {
override fun accept(i: Int): Boolean {
return i % 2 == 0
}
}
// SAM 변환을 사용하는 경우
val isEven = IntPredicate { it % 2 == 0 }
Kotlin
복사
함수형 인터페이스 생성자에 대한 호출 참조
•
Kotlin 1.6.20 이전의 인터페이스의 생성자 함수
// Printer 인터페이스와 이 인터페이스를 구현하는 익명 객체를 반환하는 생성자 함수를 정의하는 코드
interface Printer {
fun print()
}
fun Printer(block: () -> Unit): Printer = object : Printer {
override fun print() = block()
}
Kotlin
복사
•
Kotlin 1.6.20 이후의 함수형 인터페이스의 생성자 함수
•
함수형 인터페이스는 자동으로 생성자를 가지게 된다.
•
:: 키워드를 통해 함수 참조를 사용할 수 있다.
//
fun interface Printer {
fun print()
}
documentsStorage.addPrinter(::Printer)
Kotlin
복사
•
두 버전 사이 호환성을 유지하기 위해 @Deprecated 어노테이션을 사용할 수 있다.
@Deprecated(message = "Your message about the deprecation", level = DeprecationLevel.HIDDEN)
fun Printer(block: () -> Unit): Printer = object : Printer {
override fun print() = block()
}
Kotlin
복사
함수형 인터페이스 VS 타입 별칭
•
타입 별칭
◦
기존 타입에 대한 새로운 이름을 정의하는 기능이다.
◦
새로운 타입을 생성하지 않고 기존 타입에 대한 가독성을 높이기 위해 사용한다.
◦
typealias 키워드를 사용한다.
typealias IntPredicate = (i: Int) -> Boolean
val isEven: IntPredicate = { it % 2 == 0 }
fun main() {
println("7은 짝수인가? - ${isEven(7)}") // 출력: 7은 짝수인가? - false
}
Kotlin
복사
•
함수형 인터페이스
◦
단일 추상 메서드를 가지는 인터페이스로 함수형 타입을 객체로 래핑할 수 있게 해준다.
◦
함수형 인터페이스는 여러 개의 비추상 멤버를 가질 수 있으며 다른 인터페이스를 구현하거나 확장할 수 있다.
fun interface IntPredicate {
fun test(i: Int): Boolean
}
val isEven: IntPredicate = IntPredicate { it % 2 == 0 }
fun main() {
println("7은 짝수인가? - ${isEven.test(7)}") // 출력: 7은 짝수인가? - false
}
Kotlin
복사
•
차이점
1.
타입 생성
a.
타입 별칭 : 기존 타입에 대한 새로운 이름만 정의할 뿐 새로운 타입을 생성하지 않는다.
b.
함수형 인터페이스 : 새로운 타입을 생성하며 이를 통해 보다 복잡한 기능을 구현할 수 있다.
2.
멤버 수
a.
타입 별칭 : 하나의 함수 타입만을 나타낼 수 있다.
b.
함수형 인터페이스 : 여러 개의 비추상 멤버를 가질 수 있으며 하나의 추상 멤버를 가질 수 있다.
3.
확장 및 구현
a.
타입 별칭 : 다른 인터페이스를 구현하거나 확장할 수 없다.
b.
함수형 인터페이스 : 다른 인터페이스를 구현하거나 확장할 수 있다.
4.
확장 함수
a.
타입 별칭 : 확장 함수를 정의할 수 없다.
b.
함수형 인터페이스 : 특정 함수형 인터페이스에 대해 확장 함수를 정의할 수 있다.
•
선택 기준
◦
특정 매개변수와 반환 타입을 가지는 함수를 받아야 하는 API 에서는 단순한 함수 타입이나 타입 별칭을 사용하는데 좋다.
typealias StringTransformer = (String) -> String
Kotlin
복사
◦
함수 이상의 비즈니스 로직이나 계약을 가지고 있는 복잡한 엔티티가 필요한 경우 함수형 인터페이스를 선언하는 것이 좋다.
fun interface StringTransformer {
fun transform(input: String): String
// 추가적인 비추상 멤버와 메서드를 정의할 수 있습니다.
}
Kotlin
복사