Menu
Coddy logo textTech

제네릭 함수

Coddy Kotlin 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 37번째.

제네릭 함수는 모든 타입과 함께 작동합니다. 꺾쇠괄호 안에 함수 이름 앞에 작성하는 타입 매개변수는 호출자가 사용하는 타입을 나타냅니다. 일반적으로 T라는 이름을 사용합니다:

fun <T> firstOr(list: List<T>, default: T): T = if (list.isEmpty()) default else list[0]

main 내부에서:

println(firstOr(listOf(3, 5), 0) + 1)
println(firstOr(listOf<String>(), "none").uppercase())

출력:

4
NONE

Kotlin은 인수에서 타입 인자를 추론합니다. 추론할 대상이 없을 때는 위의 listOf<String>()처럼 직접 작성합니다:

fun <T> repeatItem(item: T, times: Int): List<T> = List(times) { item }

main 내부:

println(repeatItem("ab", 3))
println(repeatItem(7, 2))
val empty = repeatItem<Double>(1.5, 0)
println(empty)

출력:

[ab, ab, ab]
[7, 7]
[]

함수에는 여러 타입 매개변수가 있을 수 있으며, 함수 타입 매개변수에서 이를 사용할 수 있습니다. 다음은 map과 같은 라이브러리 함수가 모든 요소 타입과 결과 타입에 대해 작동하는 방식입니다:

fun <A, B> transform(items: List<A>, f: (A) -> B): List<B> {
    val out = mutableListOf<B>()
    for (item in items) out.add(f(item))
    return out
}

fun <K, V> invert(map: Map<K, V>): Map<V, K> = map.entries.associate { (k, v) -> v to k }

main 내부:

println(transform(listOf("kiwi", "fig")) { it.length })
println(invert(mapOf("a" to 1, "b" to 2)))

출력:

[4, 3]
{1=a, 2=b}

타입 매개변수는 호출자의 타입을 유지합니다. firstOr(listOf(3, 5), 0)은 Int를 반환하므로 + 1이 컴파일됩니다. List<Any>용으로 작성한 버전은 모든 리스트도 허용하지만, Any를 반환하므로 호출할 때마다 캐스팅해야 합니다:

fun firstAny(list: List<Any>, default: Any): Any = if (list.isEmpty()) default else list[0]
// firstAny(listOf(3, 5), 0) + 1               // 오류: Any에는 plus가 없음
(firstAny(listOf(3, 5), 0) as Int) + 1         // 컴파일되지만 캐스트가 필요함
firstOr(listOf(3, 5), 0) + 1                   // 제네릭: 결과는 Int
challenge icon

챌린지

쉬움

모든 타입의 리스트에서 작동하는 제네릭 함수 두 개를 작성하세요. countWhere(items, predicate)는 조건자 함수 (T) -> Boolean를 통과하는 요소의 개수를 반환합니다. mostCommon(items)은 가장 자주 나타나는 요소를 반환합니다(개수가 같으면 리스트에서 먼저 나타나는 요소). 빈 리스트인 경우에는 null을 반환합니다.

제공된 코드는 단어가 있는 한 줄과 숫자가 있는 한 줄을 읽고, 3글자보다 긴 단어의 개수, 가장 흔한 단어, 짝수의 개수, 가장 흔한 숫자, 그리고 빈 리스트에 대해 nothing: null을 출력합니다.

코드는 ListTools.kt에 작성하세요. Main.kt에는 제공된 입력/출력 코드가 들어 있으며 수정할 수 없습니다.

직접 해보기

fun main() {
    // 제공된 입력/출력 코드: 그대로 유지하세요
    val input = generateSequence(::readLine).toList()
    val words = input[0].split(" ")
    val numbers = input[1].split(" ").map { it.toInt() }
    println("long words: ${countWhere(words) { it.length > 3 }}")
    println("most common word: ${mostCommon(words)}")
    println("even numbers: ${countWhere(numbers) { it % 2 == 0 }}")
    println("most common number: ${mostCommon(numbers)}")
    println("nothing: ${mostCommon(listOf<String>())}")
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: Kotlin 플레이그라운드