코틀린 표준 라이브러리는 컬렉션을 위한 여러 제네릭 함수를 제공한다. 제네릭 확장 함수를 쓰려면 수신 객체 앞에 제네릭 명세(괄호로 둘러싼 타입 파라미터 목록)를 위치시켜야 한다. 예를 들어 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]에서 모두 식별자 타입에 ?를 요구한다. 시험 삼아 ?를 제거하고 어떤 오류 메시지가 표시되는지 살펴보라.

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