[Kotlin in Action] 25. SAM 생성자
- Coding/Kotlin
- 2022. 6. 19.
코틀린 람다 전달
함수형 인터페이스를 인자로 원하는 자바 메서드에 코틀린 람다를 전달할 수 있다.
자바
void postponeComputation(int delay, Runnable computation);
코틀린에서 람다를 위 함수에 넘겨보자.
postponeComputation(1000) { println(42) }
컴파일러는 자동으로 람다를 Runnable 인스턴스(Runnable을 구현한 무명 클래스의 인스턴스)로 변환해준다.
무명 클래스에 있는 유일한 추상 메서드를 구현할 때 람다 본문을 메서드 본문으로 사용한다. Runnable은 run()이 그런 추상 메서드다.
Runnable을 구현하는 무명 객체를 명시적으로 만들어서 사용할 수도 있다.
객체 식을 함수형 인터페이스 구현으로 넘긴다.
postponeComputation(1000, object : Runnable {
override fun run(){
println(42)
}
})
무명 객체는 메서드를 호출할 때마다 새로운 객체를 생성하지만, 함수의 변수에 접근하지 않는 람다에 대응하는 무명 객체를 메서드를 호출할 때마다 반복 사용한다.
프로그램 전체에서 Runnable의 인스턴스는 단 하나만 만들어진다.
postponeComputation(1000) { println(42) }
모든 handleComputation 호출에 같은 객체를 사용한다.
val runnable = Runnable { println(42) }
fun handleComputation() {
postponeComputation(1000, runnable) // 모든 handleComputation 호출에 같은 객체를 사용
}
람다 안에서 "id" 변수를 포획한다. id 필드로 저장하는 새로운 Runnable 인스턴스를 매번 새로 만들어 사용한다. 람다가 주변 영역의 변수를 포획한다면 매 호출마다 같은 인스턴스를 사용할 수 없게된다. 컴파일러는 매번 주변 영역의 변수를 포획한 새로운 인스턴스를 생성해준다.
fun handleComputation(id: String) {
postponeComputation(1000) { println(id) }
}
SAM 생성자
SAM 생성자는 람다를 함수형 인터페이스의 인스턴스로 변환할 수 있게 컴파일러가 자동으로 생성한 함수다. 컴파일러가 자동으로 람다를 함수형 인터페이스 무명 클래스로 바꾸지 못하는 경우 SAM 생성자를 사용할 수 있다.
예시) 함수형 인터페이스의 인스턴스를 반환하는 메서드가 있다면 람다를 직접 반환할 수 없고, 반환하고픈 람다를 SAM 생성자로 감싸야한다.
fun createAllDoneRunnable() : Runnable {
return Runnable { println("All done!") }
}
fun main() {
createAllDoneRunnable().run()
}
SAM 생성자의 이름은 사용하려는 함수형 인터페이스의 이름과 같다.
SAM 생성자는 그 함수형 인터페이스의 유일한 추상 메서드의 본문에 사용할 람다만을 인자로 받아서 함수형 인터페이스를 구현하는 클래스의 인스턴스를 반환한다.
람다로 생성한 함수형 인터페이스 인스턴스를 변수에 저장해야하는 경우에도 SAM 생성자를 사용할 수 있다. 여러 버튼에 같은 리스너를 적용하고 싶다면 다음 리스트처럼 SAM 생성자를 통해 람다를 함수형 인터페이스 인스턴스로 만들어서 변수에 저장해 활용할 수 있다.
val listsner = OnClickListsner { view ->
val text = when(view.id) { // view.id를 이용해 어떤 버튼이 클릭됐는지 판단한다.
R.id.button1 -> "First button"
R.id.button2 -> "Second button"
else -> "Unknown button"
}
toast(text)
}
button1.setOnClickListener(listener);
button2.setOnClickListener(listener);
'Coding > Kotlin' 카테고리의 다른 글
[Kotlin 기초문법] 총정리 (2) | 2022.10.29 |
---|---|
[Kotlin in Action] 26. 수신 객체 지정 람다 (with, apply) (0) | 2022.06.19 |
[Kotlin in Action] 24. 지연 계산(lazy) 컬렉션 연산 - 시퀀스(sequence) 사용 (0) | 2022.06.13 |
[Kotlin in Action] 23. 컬렉션 함수형 API (filter, map, all, any, count, find, groupBy, flatMap, flatten) (0) | 2022.06.01 |
[Kotlin in Action] 22. 람다식의 로컬 변수 접근, 멤버 참조 (0) | 2022.05.30 |