[Kotlin In Action] 5-4) 멤버 참조

ERyukSa·2023년 6월 22일
0

Kotlin In Action

목록 보기
4/9

람다를 사용하면 원하는 동작을 정의하고 함수에 인자로 전달할 수 있다. 그런데 원하는 동작이 이미 함수로 정의되어 있으면 어떡할까?

물론 그 함수를 호출하는 람다를 정의하면 되지만 그것은 함수 중복이다. 함수를 직접 넘길 순 없을까?

가능하다. 왜냐면 코틀린은 함수를 값처럼 다룰 수 있기 때문이다.

이중 콜론(::)을 사용하여 함수에 대한 참조를 가져올 수 있다.

val getAge = Person::age

이러한 문법을 멤버 참조라고 한다.

멤버 참조는 클래스(or인스턴스)에 접근하여 하나의 프로퍼티나 메서드에 대한 참조 값을 만들어준다.

참조된 멤버는 함수 호출 형태로 사용

재밌는 점은 메서드 참조, 프로퍼티 참조 모두 함수 호출 형태로 사용한다는 것이다.

val getAge = Person::age
val minSu = Person(name = "minSu", age = 12)
println(getAge(minSu)) // 12

age 프로퍼티에 접근하는 멤버 참조 getAge에 괄호를 붙여 사용하고 있다.

멤버 참조 = 멤버를 호출하는 람다의 축약 버전

멤버 참조는 멤버를 호출하는 람다식과 같은 타입이다. 따라서, getAge는 아래의 getAge2와 완전히 같다.

val getAge2 = { p: Person -> p.age }
println(getAge2(minSu)) // 12

아래 예시를 통해 더 분명하게 이해해보자.

people.maxByOrNull(Person::age)
people.maxByOrNull { p: Person -> p.age }
people.maxByOrNull { it.age }

위 세 개의 식은 모두 같은 역할을 한다.

인스턴스 멤버 참조

클래스 멤버 뿐만 아니라 특정 인스턴스의 멤버도 참조할 수 있다.

class Adapter(
	val getData: (offset: Int, limit: Int) -> List<Data>
)
val viewModel = ViewModel()
val adapter = Adapter(viewModel::getData)

Adapter 클래스 생성자에 viewModel 인스턴스의 getData 함수를 전달하면서 Adapter 인스턴스를 생성한다.

클래스 멤버 참조 vs 인스턴스 멤버 참조

클래스 멤버 참조를 호출하려면 인자에 그 클래스의 인스턴스를 전달해야 한다. 반면, 인스턴스 멤버 참조는 인스턴스가 정해져 있기 때문에 나머지 인자만 전달한다.

전역 멤버 참조

전역 함수도 참조할 수 있다. 클래스가 없기 때문에 ::로 참조를 바로 시작한다.

fun sendEmail(person: Person, message: String) { /* ... */}
val nextAction = ::sendEmail
nextAction(minSu, "Hi")

확장 함수 참조

확장 함수도 멤버 함수와 같은 방식으로 참조할 수 있다.

fun Person.isAdult = this.age >= 20
val predicate: (Person) -> Boolean = Person::isAdult
predicate(minSu) // false

정리

멤버 참조를 통해 기존에 정의된 함수를 다른 함수에 전달할 수 있다. [클래스::멤버] 형태로 사용하며, 멤버 참조는 람다의 축약 형태이다.

0개의 댓글