더북(TheBook)

코틀린 표준 라이브러리는 컬렉션을 위한 여러 제네릭 함수를 제공한다. 제네릭 확장 함수를 쓰려면 수신 객체 앞에 제네릭 명세(괄호로 둘러싼 타입 파라미터 목록)를 위치시켜야 한다. 예를 들어 first()firstOrNull() 정의를 살펴보자.

IntroGenerics/GenericListExtensions.kt

package introgenerics
import atomictest.eq

fun <T> List<T>.first(): T {
  if (isEmpty())
    throw NoSuchElementException("Empty List")
  return this[0]
}

fun <T> List<T>.firstOrNull(): T? =
  if (isEmpty()) null else this[0]

fun main() {
  listOf(1, 2, 3).first() eq 1
  val i: Int? =                  // [1]
    listOf(1, 2, 3).firstOrNull()
  i eq 1
  val s: String? =               // [2]
    listOf<String>().firstOrNull()
  s eq null
}

first()firstOrNull()은 모든 List에 대해 작동할 수 있다. T 타입의 값을 반환하기 위해서는 제네릭 함수로 이 두 함수를 정의해야만 한다.

firstOrNull()에서 어떻게 반환 타입을 널이 될 수 있는 타입으로 명시했는지 살펴보라.

[1] List<Int>에 대해 firstOrNull()을 호출하면 Int?가 반환되는 모습을 보여준다.

[2] List<String>에 대해 같은 함수를 호출해서 String?를 받는다.

코틀린은 [1][2]에서 모두 식별자 타입에 ?를 요구한다. 시험 삼아 ?를 제거하고 어떤 오류 메시지가 표시되는지 살펴보라.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.