Home Kotlin SAM
Post
Cancel

Kotlin SAM

android를 kotlin으로 개발하다보면 다음과 같은 코드를 자주 작성하게 된다.

1
2
3
view.setOnClickListener {
    ...
}

코틀린 특성상 메소드의 마지막 파라미터가 람다식인 경우 () 뒤에 { ... } 블록을 작성할 수 있다.


하지만 view.setOnClickListener 메소드를 확인해보면 다음과 같이 정의되어 있다.

1
2
3
public void setOnClickListener(@Nullable OnClickListener l) {
    ...
}

여기서 OnClickListener 는

1
2
3
public interface OnClickListener {
    void onClick(View v);
}

setOnClickListener의 파라미터인 OnClickListener 람다식이 아니지만, 람다식처럼 취급되고 있다.
이것이 가능한 이유는 자바8부터 지원한 SAM(single abstract method) 라는 특성 때문인데,
interface가 오직 하나의 abstract method 를 가지고 있는 경우 람다로 wrapping 해주는 특성이다.
코틀린 또한 SAM을 지원하기에 자바의 OnClickListener 를 람다로 wrapping 해준 것.


문제는 코틀린으로 OnClickListener을 똑같이 정의할 경우
SAM conversion이 적용되지 않는다.
왜일까 ?

https://stackoverflow.com/questions/55116769/interface-as-functions-in-kotlin/55117201
스택오버플로를 참고해보면,
kotlin에는 적절한 함수 유형이 있으므로 함수를 자동 변환할 필요가 없어 지원하지 않는다고 한다.

해당 페이지 안에는 참조 링크로 공식 문서인 https://kotlinlang.org/docs/java-interop.html#sam-conversions
링크를 주는데, 현재는 코틀린이 업데이트 되면서 공식 문서에서 해당 문장이 빠진 것으로 보인다.



그럼 코틀린으로 작성된 것에 대해서는 SAM 변환을 지원하지 않는것인가?
jetbrains쪽 이슈를 보면 https://youtrack.jetbrains.com/issue/KT-7770?source=post_page---------------------------
SAM 지원에 대해 열띤 얘기를 나눈 것을 확인할 수 있다.

object: 익명 클래스 작성은 코틀린 답지 못하다고 다들 느끼고 있었던 것으로 생각된다.

Denis Zharkov 가 20 Jun 2018 15:28 에 추가한 코멘트를 확인해보면, ( 1.3 출시 전으로 보임 )
1.0 부터 해당 이슈를 인지하고 있었고, 지원을 준비하고 있었지만 여러 복잡한 이슈들을 해결하다보니 시간이 걸렸다고 한다.
이 때 맛보기로 소개한 아래의 코드.

1
2
3
fun interface MyRunnable {
  fun run()
}

interface 앞에 fun 키워드를 붙인 것으로 SAM conversion을 지원할 것이라고 한다.
결국 코틀린 1.4에서 해당 기능이 적용이 되었다.
https://blog.jetbrains.com/ko/kotlin/2020/07/kotlin-1-4-m3-ko/#fun-interfaces-in-stdlib

이건 현재 가이드
https://kotlinlang.org/docs/fun-interfaces.html

보통은 개발하다보면 모양이 변형되기 마련인데 2018년 6월에 언급된 아이디어가 2020년 7월에 그대로 공개된 부분이 대단하기도 하다. fun interface 키워드가 워낙 찰떡이라 그런 것 같기도.

말그대로 fun interface …😅

This post is licensed under CC BY 4.0 by the author.