함수, 프로퍼티, 생성자에 대해서 호출하는 뻔한 람다를 대신할 수 있다. 사용법은 클래스 이름과 콜론 2개를 연결시켜 사용하면 된다. 관련된 내용은 아래 예제를 통해 확인해 볼 수 있다.
data class Message(
val sender: String,
val text: String,
val isRead: Boolean
)
fun propertyReferenece() {
val messages = listOf(
Message("Kitty", "Hey!", true),
Message("Kitty", "Where are you?", false)
)
val unread1 = messages.filterNot(Message::isRead)
val unread2 = messages.filterNot { it.isRead }
println(unread1.size)
println(unread2.size)
println(unread1.single().text)
println(unread2.single().text)
}
Message라는 data class를 만들고 message list 중에서 읽지 않은 것만 필터해서 가지고 오는 로직이다. 이 때 보통 사용할 수 있는 it.isRead 대신에 "클래스이름::함수이름"과 같은 방법으로 사용할 수 있다. 아래 처럼 실행 결과는 동일함을 알 수 있다.
정렬 순서를 지정할 때에도 유용하게 사용할 수 있다.
fun sortWith() {
val messages = listOf(
Message("Kitty", "Hey!", true),
Message("Kitty", "Where are you?", false),
Message("Boss", "Meeting today", false)
)
val sortedMessages = messages.sortedWith(compareBy(
Message::isRead, Message::sender
))
println(sortedMessages)
}
compareBy에 isRead와 sender를 멤버 참조 형식으로 전달하였다. compareBy에 인자를 하나만 넘기고 sortedWith에 전달하면 sortedBy와 같은 결과를 얻을 수 있다.
함수도 참조로 넘길 수 있다. 메시지가 중요한지의 여부를 결정하는 함수를 별도로 만들어 두고 이를 넘겨서 메시지 리스트를 검사할 수 있다.
data class Message(
val sender: String,
val text: String,
val isRead: Boolean,
val attachments: List<Attachment>
)
data class Attachment(
val type: String,
val name: String
)
fun Message.isImportant(): Boolean =
text.contains("Salary increase") ||
attachments.any {
it.type == "image" &&
it.name.contains("cat")
}
fun functionReference() {
val messages = listOf(
Message("Boss", "Let's discuss goals for next year", false, listOf(Attachment("image", "cute cats")))
)
val result = messages.any(Message::isImportant)
println(result)
}
Message class에 isImportant 라는 함수를 확장한다.
해당 함수는 내용에 "Salary increase"라는 문구가 들어가 있거나, 첨부 파일이 이미지 파일이면서 파일명에 "cat"이 들어가 있는 경우이다.
정의 된 isImportant 함수를 any 안에 "Message::isImportant" 처럼 작성해서 함수 참조로 넘길 수 있다. 결과는 아래와 같다.
어떤 클래스에 소속된 함수가 아니라 최상위 함수라면 "클래스명::함수명" 처럼 사용하지 않고 그냥 "::함수명"처럼 사용할 수 있다.
생성자도 참조할 수 있다. 다음의 코드를 보면 바로 알 수 있다.
data class Student(
val id: Int,
val name: String
)
fun constructorReference() {
val names = listOf("Alice", "Bob")
val students1 = names.mapIndexed { index, name -> Student(index, name) }
println(students1)
val students2 = names.mapIndexed(::Student)
println(students2)
}
람다처럼 사용할 수 있고, Student가 최상위에 있으므로 "::Student" 처럼 생성자를 참조로 넘길 수도 있다. 실행 결과는 아래와 같다.
'Develop! > Kotlin' 카테고리의 다른 글
고차함수, 리스트 조작 in Kotlin (0) | 2023.10.04 |
---|---|
컬렉션에 대한 연산 in Kotlin (0) | 2023.09.25 |
람다 in Kotlin (0) | 2023.09.25 |
제네릭스 in Kotlin (0) | 2023.09.22 |
안전한 호출과 엘비스 연산자 in kotlin (0) | 2023.09.14 |