추상 메서드가 하나만 있는 인터페이스를 함수형 인터페이스(Functional Interface) 또는 단일 추상 메서드(Single Abstract Method) 인터페이스 라고 한다. 함수형(Functional) 인터페이스는 여러 비추상 멤버를 가질 수 있지만 추상 멤버는 하나만 가질 수 있다.
함수형 인터페이스를 선언하려면 fun 한정자를 사용하면 된다.
fun interface KRunnable {
fun invoke()
}
SAM 변환
SAM 변환을 쓰면 함수형 인터페이스를 람다 식을 이용하여 코드를 더 간결하고 읽기 쉽게 바꿀 수 있다.
매번 함수형 인터페이스를 상속하는 클래스를 생성하는 것 대신, 람다 식으로 간결하게 줄일 수 있다.
SAM변환을 이용하면 코틀린은 시그니처가 인터페이스 단일 메서드의 시그니처와 일치하는 모든 람다식을 인터페이스 구현을 동적으로 인스턴스화 하는 코드로 변환할 수 있다.
signature란 함수 또는 메서드의 이름, 매개변수, 리턴타입의 조합을 말한다.
우선 SAM변환을 사용하지 않은 예제를 보자
fun main(){
val isEven = object: KTest{
override fun invoke(i: Int): Boolean {
return i % 2 == 0
}
}
println("50은 짝수? : ${isEven.invoke(50)}")
}
fun interface KTest {
fun invoke(i: Int): Boolean
}
-결과-
50은 짝수? : true
SAM변환을 쓰면 isEven에 할당된 상속문을 람다 식으로 간결하게 바꿀 수 있다.
fun main(){
val isEven = KTest{ it % 2 == 0}
println("50은 짝수? : ${isEven.invoke(50)}")
}
fun interface KTest {
fun invoke(i: Int): Boolean
}
-결과-
50은 짝수? : true
이또한 자바에서 사용가능하다.
생성자 함수가 있는 인터페이스에서 함수형 인터페이스로 마이그레이션
1.6.20부터 코틀린은 함수형 인터페이스 생성자에 대해 리플렉션을 지원하여 생성자 기능이 있는 인터페이스에서 함수형 인터페이스로 마이그레이션 하는 소스 호환 방법을 추가한다.
interface Printer {
fun print()
}
fun Printer(block: () -> Unit): Printer = object : Printer {
override fun print() = block()
}
함수형 인터페이스 생성자에 대해 리플렉션을 활성화하면 이 코드를 함수형 인터페이스 선언만으로 대체할 수 있다.
fun interface Printer {
fun print()
}
생성자는 암시적으로 생성되며 ::Printer 함수 참조를 사용하는 모든 코드는 컴파일된다.
documentsStorage.addPrinter(::Printer)
주석이 있는 레거시 함수 Printer를 아래 방법으로 바이너리 호환성을 유지할 수 있다.
@Deprecated(message = "Your message about the deprecation", level = DeprecationLevel.HIDDEN)
fun Printer(...) {...}
함수형 인터페이스 vs type aliases(별칭 형식)
함수형 인터페이스를 typealias를 사용하여 간단하게 다시 작성할 수 있다.
typealias KTest = (i: Int) -> Boolean
fun main(){
val isEven: KTest = { it % 2 == 0}
println("7이 짝수? : ${isEven(7)}")
}
-결과-
7이 짝수? : false
함수형 인터페이스와 type aliases는 용도가 다르다. type aliases는 기존 타입의 이름일 뿐이며, 함수형 인터페이스가 하는 것처럼 새로운 타입을 생성하지 않는다. 일반 함수 또는 type aliases에 적용할 수 없도록 함수형 인터페이스에 특정한 확장을 제공할 수 있다.
type aliases는 하나의 멤버만 가질 수 있는 반면 함수형 인터페이스는 여러 비추상 멤버와 하나의 추상 멤버를 가질 수 있다. 함수형 인터페이스는 다른 인터페이스를 상속하고 확장할 수 있다.
함수형 인터페이스는 type aliases보다 더 유연하고 많은 기능을 제공하지만 인터페이스로 변환해야 기능을 이용할 수 있기 때문에 런타임에 비용이 더 많이 들 수 있다. 따라서 요구사항에 따라 고려하면 된다.
- API가 일부 특정 매개변수 및 반환 유형이 있는 함수(모든 함수)를 허용해야 하는 경우 간단한 함수형 타입을 쓰거나 type alias을 사용하여 함수형 타입에 짧은 이름을 지정할 수 있다.
- API가 함수보다 더 복잡한 엔티티를 허용하는 경우, 이에 대한 별도의 함수형 인터페이스를 선언한다.
참고
Functional (SAM) interfaces | Kotlin
kotlinlang.org
'코틀린' 카테고리의 다른 글
확장(Extensions) (0) | 2023.03.07 |
---|---|
가시성 수식어(Visibility modifiers) (0) | 2023.02.02 |
인터페이스 (0) | 2023.02.01 |
프로퍼티와 필드 (0) | 2023.01.31 |
클래스와 상속 (0) | 2023.01.30 |