Chapter9. 제네릭스

김신영·2022년 10월 25일
0

kotlin-in-action

목록 보기
11/11
post-thumbnail
  • Kotlin 컴파일러는 타입 추론과 마찬가지로 제네릭 타입 인자도 추론할 수 있다.

  • 제네릭 메서드, 제네릭 확장 함수, 제네릭 최상위 함수

  • 제네릭 확장 프로퍼티

  • 제네릭 프로퍼티는 불가능

  • 제네릭 클래스, 제네릭 인터페이스

타입 파라미터 제약 (type paramter constraint)

fun <T: Comparable<T>> max(first: T, second: T): T {  
    return if (first > second) first else second  
}  
  
fun main(args: Array<String>) {  
    println(max("kotlin", "java"))  
}

타입 파라미터에 여러 제약을 가하기 where

  • where
fun <T> ensureTrailingPeriod(seq: T)  
        where T : CharSequence, T : Appendable {  
    if (!seq.endsWith('.')) {  
        seq.append('.')  
    }  
}  
  
fun main(args: Array<String>) {  
    val helloWorld = StringBuilder("Hello World")  
    ensureTrailingPeriod(helloWorld)  
    println(helloWorld)  
}

널이 될수 없는 타입으로 한정 <T: Any>

fun <T> process(value: T) = value?.hashCode()  
  
fun <T: Any> process2(value: T) = value.hashCode()

fun main(args: Array<String>) {  
    println(process<String?>(null))  // null
    
    println(process2<String?>(null))  
    // Compile Error: Type Argument is not within its bounds.  
}  
  

실행 시 제네릭스의 동작: 소거된 타입 파라미터와 실체화된 타입 파라미터

  • 사용 지점 변성 (use-site variance)
  • 선언 지점 변성 (declaration-site variance)

타입 소거 (type erasure)

  • 자바와 마찬가지로 코틀린 제네릭 타입 인자 정보는 런타임에 지워진다. (type erasure)

Star Projection <*>

  • 자바의 List<?> 와 비슷하다.
  • 인자를 알 수 없는 제네릭 타입을 표현할 때 사용한다.
@Suppress("UNCHECKED_CAST")  
fun printSum(c: Collection<*>) {  

    // Unchecked cast: Collection<*> to List<Int>  
    val intList = c as? List<Int>  
            ?: throw IllegalArgumentException("List is expected")  
            
    println(intList.sum())  // 6
}  
  
fun main(args: Array<String>) {  
    printSum(listOf(1, 2, 3))  
    // 6
    
    printSum(setOf(1, 2, 3))   
    // IllegalArgumentException: List is expected
    
    printSum(listOf("a", "b", "c"))  
    // ClassCastException: java.lang.String cannot be cast to java.lang.Number
}
  • 컴파일 시점에 알려진 파라미터 타입 인자의 정보가 주어진 경우에는 is 검사 가능
fun printSum(c: Collection<Int>) {  
    if (c is List<Int>) {   // 이 검사는 올바르다.  
        println(c.sum())  
    }  
}  
  
fun main(args: Array<String>) {  
    printSum(listOf(1, 2, 3))   // 6  
    printSum(setOf(1, 2, 3))    // 출력없음.  
}

실체화한 타입 파라미터를 사용한 함수 선언

  • 타입 파라미터를 <reified T> 로 선언해야 한다.
  • 함수를 inline함수로 정의해야 한다.
inline fun <reified T> isA(value: Any) = value is T  
  
fun main(args: Array<String>) {  
    println(isA<String>("abc"))  
    println(isA<String>(123))  
}
profile
Hello velog!

0개의 댓글