[Kotlin] 고차 함수, 람다 함수, 확장 함수 그리고 속성

고차 함수(Higher-Order Functions), 람다 함수(Lambda Functions), 확장 함수(Extension Functions) 그리고 속성(Properties)에 대해 알아봅니다.
vmkmym's avatar
Apr 19, 2024
[Kotlin] 고차 함수, 람다 함수, 확장 함수 그리고 속성

고차 함수 (Higher-Order Functions)

고차 함수는 함수를 매개변수로 받거나 함수를 반환하는 함수입니다. 코틀린에서는 함수가 일급 객체이기 때문에 이런 기능이 가능합니다. 일급 객체는 변수에 담을 수 있고, 함수의 인자로 넘길 수 있으며, 함수의 반환값으로 사용할 수 있는 조건을 만족한다는 뜻입니다.
// 1. 함수를 변수에 담기 val greeting = { println("Hello") } greeting() // 실행됨 // 2. 함수를 인자로 전달하기 fun runOperation(operation: () -> Unit) { operation() } runOperation(greeting) // 3. 함수를 반환값으로 사용하기 fun getGreeting(): () -> Unit { return { println("Hi from returned function") } } val greet = getGreeting() greet()
 

🔹 예제 1: 함수를 변수에 담기

  • greeting이라는 변수에 람다 함수(이름 없는 함수)를 할당합니다.
  • 이 람다 함수를 greeting이라는 변수에 저장한 것입니다.
  • 그래서 변수 이름 뒤에 ()를 붙이면 그 함수를 실행할 수 있습니다.
👉 즉, println("Hello")를 출력하는 함수를 변수에 담아 놓고 나중에 실행한 거예요.
 

🔹 예제 2: 함수를 다른 함수의 인자로 넘기기

  • runOperation 함수는 다른 함수를 매개변수로 받는 함수예요.
  • operation: () -> Unit는 "매개변수 operation입력 없고 출력도 없는 함수 타입이야"라는 뜻이에요.
  • operation() → 받은 함수를 실행하는 거예요.
  • runOperation(greeting) → 아까 만든 greeting 함수를 넘겨서 실행한 거예요.
👉 함수도 숫자처럼 다른 함수에 전달할 수 있다는 걸 보여줘요.
 

🔹 예제 3: 함수를 리턴값으로 주기

  • getGreeting()함수를 반환하는 함수예요.
  • () -> Unit은 "입력 없고 출력도 없는 함수"라는 뜻이에요.
  • getGreeting()을 호출하면 { println("Hi from returned function") } 람다를 돌려줘요.
  • 그걸 greet라는 변수에 담고, greet()로 실행한 거예요.
👉 이건 함수가 반환값이 될 수 있다는 걸 보여줘요.
 
// 고차 함수를 활용한 데이터 필터링 예시 fun <T> Collection<T>.customFilter(predicate: (T) -> Boolean): List<T> { val result = mutableListOf<T>() for (item in this) { if (predicate(item)) { result.add(item) } } return result } fun main() { val fruits = listOf("Apple", "Banana", "Cherry", "Dragonfruit", "Elderberry") // 5글자보다 긴 과일 찾기 val longFruits = fruits.customFilter { it.length > 5 } println("Long fruits: $longFruits") // 출력: [Banana, Cherry, Dragonfruit, Elderberry] // 'e'를 포함하는 과일 찾기 val fruitsWithE = fruits.customFilter { it.contains('e') } println("Fruits with 'e': $fruitsWithE") // 출력: [Apple, Cherry, Elderberry] }
 

람다 함수 (Lambda Functions)

람다 함수는 이름 없이 즉시 사용하는 함수식으로 람다식은 중괄호 {} 안에 정의하고 매개변수가 있으면 → 기호로 구분해요. Kotlin으로 코드를 작성하다보면 람다 함수를 자주 사용하게 되는데 다음과 같이 작성합니다.
 
data class Student(val name: String, val age: Int, val grade: Double) fun main() { val students = listOf( Student("Alice", 20, 3.8), Student("Bob", 22, 3.2), Student("Charlie", 19, 4.0), Student("Diana", 21, 3.5) ) // 람다를 활용한 데이터 처리 파이프라인 val honorStudents = students .filter { it.grade >= 3.5 } .sortedByDescending { it.grade } .map { "${it.name} (GPA: ${it.grade})" } println("Honor Students:") honorStudents.forEach { println("- $it") } // 출력: // Honor Students: // - Charlie (GPA: 4.0) // - Alice (GPA: 3.8) // - Diana (GPA: 3.5) }
 
 

확장 함수 (Extension Functions)

확장 함수는 기존 클래스에 새로운 함수를 추가하는 기능입니다. 라이브러리나 프레임워크의 코드를 수정하지 않고도 새로운 기능을 추가할 수 있습니다.
 
마찬가지로 데이터를 받아서 UI에 표시할 때 날짜 처리를 해야하는 경우가 생기는데 다음과 같은 예시로 확장 함수를 이용합니다.
import java.time.LocalDate import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit // LocalDate 클래스에 대한 확장 함수들 fun LocalDate.formatKorean(): String { return this.format(DateTimeFormatter.ofPattern("yyyy년 MM월 dd일")) } fun LocalDate.daysUntil(other: LocalDate): Long { return ChronoUnit.DAYS.between(this, other) } fun LocalDate.isWeekend(): Boolean { val dayOfWeek = this.dayOfWeek.value return dayOfWeek == 6 || dayOfWeek == 7 // 토요일(6) 또는 일요일(7) } fun main() { val today = LocalDate.now() val futureDate = today.plusDays(10) println("오늘: ${today.formatKorean()}") println("10일 후: ${futureDate.formatKorean()}") println("남은 일수: ${today.daysUntil(futureDate)}일") println("오늘은 주말인가요? ${today.isWeekend()}") }
 

확장 속성 (Extension Properties)

코틀린에서 확장 속성은 확장 함수와 마찬가지로 클래스에 확장 속성도 추가할 수 있습니다.
 
// String 클래스에 확장 속성 추가 val String.wordCount: Int get() = this.split(Regex("\\s+")).filter { it.isNotEmpty() }.size val String.vowelCount: Int get() = this.count { it.lowercase() in "aeiou" } val String.isEmail: Boolean get() = matches(Regex("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}$")) fun main() { val text = "The quick brown fox jumps over the lazy dog" println("단어 수: ${text.wordCount}") // 출력: 9 println("모음 수: ${text.vowelCount}") // 출력: 11 val email1 = "user@example.com" val email2 = "invalid-email" println("$email1 은 유효한 이메일인가? ${email1.isEmail}") // 출력: true println("$email2 은 유효한 이메일인가? ${email2.isEmail}") // 출력: false }
 
 

정리

코틀린의 고차 함수, 람다, 확장 함수와 속성은 코드를 더 간결하고 표현력 있게 만들어 줍니다. 다음과 같은 이점이 있습니다.
  • 코드 재사용성 향상
  • 함수형 프로그래밍 지원
  • API 설계의 유연성 (다양한 콜백과 리스너를 더 간결하게 구현)
 
Share article

code-with-me