티스토리 뷰

발단

오브젝트가 함수형 인터페이스면 접두어로 인터페이스 파입을 가진 람다를 생성할 수 있다하여 따라해봄.

@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 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/

 

Kotlin SAM(Single Abstract Method)을 사용하는 방법

개인 광고 영역 Kotlin에는 SAM Conversions이 제공됩니다. Single Abstract Method의 약자로 SAM이라고 합니다. 이름에서 알 수 있듯 SAM은 하나의 추상 메서드에 대해서 lambdas 식을 제공합니다. 단, Java에서 작성한 Interface 정의와 이를 활용하는 setOnClickListener를 kotlin에서 부르는 경우에만 이에 해당합니다. 코틀린에서 유용해야 하는데 실제로는 kotlin에서 작성한 interf

thdev.tech

https://makeappeasy.com/android/2018/08/21/sam-in-kotlin/

 

SAM in Kotlin – Android

SAM(Single Abstract Method) : Kotlin은 SAM conversion을 지원하지 않는다. 좀 더 정확히 말하면 Kotlin으로 작성되었을 경우에 지원하지 않는다. 왜냐하면 함수 타입 선언으로 가능하기 때문이다.  말이 좀 어렵다.  먼저 자바에서 어떻게 사용되는지 부터 보자. public interface Callable{ void call(String value); } public interface Callable{    voi

makeappeasy.com

https://stackoverflow.com/questions/43737785/kotlin-interface-does-not-have-constructors

 

Kotlin: Interface ... does not have constructors

I am converting some of my Java code to Kotlin and I do not quite understand how to instantiate interfaces that are defined in Kotlin code. As an example, I have an interface (defined in Java code):

stackoverflow.com

 

댓글