티스토리 뷰
728x90
발단
오브젝트가 함수형 인터페이스면 접두어로 인터페이스 파입을 가진 람다를 생성할 수 있다하여 따라해봄.
@FunctionalInterface
interface FunctionalInterface {
fun apply()
}
fun main() {
val f = FunctionalInterface { println() } // error??
}
그런데 생성이 안되고 에러가 발생함.. 뭐지??
함수형 인터페이스를 잘못 선언했나 해서 기존에 있는 클래스를 가지고 다시 시도해봄.
fun main() {
val r = Runnable { println("run!") }
r.run() // run!
}
이건 잘됨;;; 뭐지??
그래서 Runnable을 코틀린으로 가져와 다시 시도해봄
@FunctionalInterface
interface RunnableKotlin {
fun run()
}
fun main() {
val r = RunnableKotlin { println("kotlin run!!") } // error
}
마찬가지로 또 에러발생;; 뭐지???
스택 오버플로우 검색해보니...
Your Java code relies on SAM conversion - an automatic conversion of a lambda into an interface with a single abstract method. SAM conversion is currently not supported for interfaces defined in Kotlin.
훔..... SAM Conversion????
SAM Conversion
- SAM은 Single Abstract Method의 약자로 코틀린의 함수 리터럴을 자동으로 자바의 함수형 인터페이스로 교체해 준다.
- 즉, SAM Conversion은 자바로 작성한 Functioncal Interface에서만 동작하여 코틀린으로 작성시에는 사용하지 못한다.
- 이 기능은 자바와 상호 운영성 측면에서 나왔으며 코틀린의 경우 함수형 인터페이스가 아닌 함수타입으로 선언이 가능하다.
//Java
@FunctionalInterface
public interface JavaFunctionalInterface {
void apply();
}
//Kotlin
fun main() {
val f = JavaFunctionalInterface { println("java functional interface") }
f.apply() // java functional interface
}
interface KotlinFunctionalInterface { fun apply() }
class KotlinFunctionalClass(val f: KotlinFunctionalInterface)
class KotlinFunctionalClassAnother(val f: () -> Unit) // 함수형 타입으로 파라미터 선언
class JavaFunctionalClass(val f: JavaFunctionalInterface)
fun main() {
val j = JavaFunctionalInterface { println("java functional interface") }
JavaFunctionalClass(JavaFunctionalInterface { println("") })
j.apply() // java functional interface
// val k = KotlinFunctionalClass { println("java functional interface") } // error
val k = KotlinFunctionalClassAnother(f = { println("kotlin lambda") })
k.f.invoke() // kotlin lambda
}
위와 같이 자바에서 선언한 함수형 인터페이스는 SAM Conversion이 가능하지만 코틀린에서 선언한 함수형 인터페이스는 사용하지 못한다.
만약 함수형 파라미터를 받고자 한다면 인터페이스가 아닌 함수형 파라미터를 선언해서 사용해야한다.
val f: () -> Unit
만약 위의 함수형 타입 선언이 장황하거나 재사용 또는 가독성 측면에서 typealias를 사용할 수도 있다.
typealias emptyFuncType = () -> Unit
class KotlinFunctionalClassAnother(val f: emptyFuncType) // 함수형 타입으로 파라미터 선언
fun main() {
val k = KotlinFunctionalClassAnother(f = { println("kotlin lambda") })
k.f.invoke() // kotlin lambda
}
출처
https://thdev.tech/kotlin/androiddev/2017/10/07/Kotlin-SAM/
https://makeappeasy.com/android/2018/08/21/sam-in-kotlin/
https://stackoverflow.com/questions/43737785/kotlin-interface-does-not-have-constructors
728x90
'개발 언어 > 코틀린' 카테고리의 다른 글
코틀린(Kotlin) | 클래스 - Enum (0) | 2019.06.24 |
---|---|
코틀린(Kotlin) | 클래스 - 프로퍼티(Property) (2) | 2019.06.24 |
코틀린(Kotlin) | 클래스 - 중첩 클래스와 내부 클래스 (0) | 2019.06.24 |
코틀린(Kotlin) | 제네릭 (Generic) (0) | 2019.06.23 |
코틀린(Kotlin) | 클래스 - 데이터 클래스 (0) | 2019.06.22 |
댓글