안드로이드 개발자 노트
[이펙티브 코틀린] Item38. 연산 또는 액션을 전달할 때는 인터페이스 대신 함수 타입을 사용하라 본문
Kotlin/이펙티브 코틀린
[이펙티브 코틀린] Item38. 연산 또는 액션을 전달할 때는 인터페이스 대신 함수 타입을 사용하라
어리둥절범고래 2023. 12. 31. 12:51반응형
대부분의 프로그래밍 언어에는 함수 타입이 없어서 연산 또는 액션을 전달할 때 메서드가 하나만 있는 인터페이스를 활용합니다.
이러한 인터페이스를 SAM(Single-Abstract Method)이라고 부릅니다.
함수가 SAM을 받는다면, 이러한 인터페이스를 구현한 객체를 전달받는다는 의미입니다.
예를 들어 다음 코드는 뷰를 클릭했을 때 발생하는 정보를 전달하는 SAM입니다.
interface OnClick {
fun clicked(view: View)
}
fun setOnclickListener(listener: Onclick) {
// ...
}
setOnClickListener(object: Onclick {
override fun clicked(view: View) {
// ...
}
})
함수 타입을 사용하는 코드로 변경하면 다음과 같습니다.
fun setOnClickListener(listener: (View) -> Unit) {
// ...
}
이렇게 하면 더 많은 자유를 얻을 수 있으며, 다음과 같은 방법으로 파라미터를 전달할 수 있습니다.
// 람다 표현식 또는 익명 함수로 전달
setOnClickListener { /* ... */ }
setOnClickListener(fun(view) { /* ... */ })
// 함수 레퍼런스 또는 제한된 함수 레퍼런스로 전달
setOnClickListener(::println)
setOnClickListener(this::showUsers)
// 선언된 함수 타입을 구현한 객체로 전달
class ClickListener: (View)->Unit {
override fun invoke(view: View) {
// ...
}
}
타입 별칭(type aliase)을 사용하면, 함수 타입도 이름을 붙일 수 있습니다.
typealias OnClick = (View) -> Unit
파라미터도 이름을 가질 수 있습니다.
이름을 붙이면, IDE의 지원을 받을 수 있다는 장점이 있습니다.
fun setOnClickListener(listener: OnClick) { /*...*/ }
typealias OnClick = (view: View, id: Int)->Unit
람다 표현식을 사용할 때는 아규먼트 분해(destructure argument)도 사용할 수 있습니다.
고전적인 자바는 다음과 같이 인터페이스를 기반으로 구현했습니다.
class CalendarView {
var listenr: Listener? = null
interface Listener {
fun onDateClicked(date: Date)
fun onPageChanged(date: Date)
}
}
함수 타입을 따로따로 갖는 것이 훨씬 사용하기 쉬우며, 각각의 것을 독립적으로 변경할 수 있습니다.
class CalendarView {
fun onDateClicked((date: Date) -> Unit)? = null
fun onPageChanged((date: Date) -> Unit)? = null
}
딱 한 가지 경우에만 SAM을 사용하는 것이 좋습니다.
코틀린이 아닌 다른 언어에서 사용할 클래스를 설계할 때입니다.
함수 타입으로 만들어진 클래스는 자바에서 타입 별칭과 IDE의 지원을 받을 수 없으며, Unit을 명시적으로 리턴하는 함수가 필요합니다.
// 코틀린
class CalendarView() {
var onDateClicked: ((date: Date) -> Unit)? = null
var onPageChanged: OnDateClicked? = null
}
interface onDateClicked {
fun onClick(date: Date)
}
// 자바
CalendarView c = new CalendarView();
c.setOnDateClicked(date -> Unit.INSTANCE);
c.setOnPageChanged(date -> {});
반응형
'Kotlin > 이펙티브 코틀린' 카테고리의 다른 글
[이펙티브 코틀린] Item39. 태그 클래스보다는 클래스 계층을 사용하라 (0) | 2023.12.31 |
---|---|
[이펙티브 코틀린] Item37. 데이터 집합 표현에 data 한정자를 사용하라 (0) | 2023.12.31 |
[이펙티브 코틀린] Item36. 상속보다는 컴포지션을 사용하라 (0) | 2023.12.30 |