본문 바로가기
Android

[Kotlin] 제네릭

by 박매트 2024. 11. 12.

코틀린에서 제네릭(Generic)여러 타입에 대해 유연하게 코드를 작성할 수 있도록 도와주는 기능입니다.
제네릭은 클래스, 함수, 인터페이스에서 특정 타입에 종속되지 않고 다양한 타입을 처리할 수 있게 합니다.
제네릭을 사용하면 코드 중복을 줄이고 타입 안전성을 높일 수 있습니다.

제네릭의 기본 개념

제네릭은 타입 매개변수(type parameter)를 사용하여 클래스나 함수를 정의할 때 특정 타입에 의존하지 않게 합니다.
이 타입 매개변수는 코드가 실행되기 전에 실제 타입으로 대체됩니다.

제네릭 클래스

class Box<T>(val item: T)

fun main() {
    val intBox = Box(1)      // T는 Int로 대체
    val stringBox = Box("Hello") // T는 String으로 대체

    println(intBox.item)      // 출력: 1
    println(stringBox.item)   // 출력: Hello
}

 
위의 예제에서 Box<T>는 제네릭 클래스로, T는 타입 매개변수입니다. 실제로 intBox는 Box<Int>, stringBox는 Box<String>으로 대체됩니다.

제네릭 함수

제네릭 함수는 특정 타입에 구애받지 않고 다양한 타입을 처리할 수 있습니다.

제네릭 제약 (Generics Constraints)

제네릭은 때로는 특정 타입만 허용하도록 제약을 걸 수 있습니다. 예를 들어, 제네릭 타입 T가 특정 클래스나 인터페이스를 상속해야 한다는 조건을 추가할 수 있습니다.

 

제네릭의 가변성 (Variance)

코틀린에서 제네릭 타입의 가변성은 제네릭 타입이 다른 타입들 간에 어떻게 변환될 수 있는지를 정의합니다. 이는 주로 공변성(covariance), 반공변성(contravariance), 무변성(invariance)으로 나뉩니다.

 

1. 공변성 (out): 상위 타입을 허용하는 경우

  • 공변성은 제네릭 타입이 해당 타입의 하위 타입일 때 이를 상위 타입으로 간주할 수 있음을 의미합니다. 주로 읽기 전용인 경우에 사용됩니다.
  • out 키워드는 공변성을 나타냅니다.
 
 

2. 반공변성 (in): 하위 타입을 허용하는 경우

  • 반공변성은 제네릭 타입이 상위 타입일 때 이를 하위 타입으로 간주할 수 있음을 의미합니다. 주로 매개변수로 쓰일 때 사용됩니다.
  • in 키워드는 반공변성을 나타냅니다.
 

3. 무변성 (Invariance): 상위/하위 타입 모두 허용하지 않음

  • 기본적으로 제네릭은 무변성입니다. 즉, Box<Int>는 Box<Number>로 간주될 수 없습니다. 상위/하위 타입 관계 없이 동일한 타입이어야 합니다.
 
 

제네릭의 실체화된 타입 파라미터 (Reified Type Parameter)

코틀린은 런타임에 타입 정보가 삭제되는 **타입 소거(Type Erasure)**를 사용합니다.

하지만 실체화된 타입 파라미터(reified)를 사용하면, 런타임에 제네릭 타입에 대한 정보를 유지할 수 있습니다.

이 기능은 인라인 함수와 함께 사용됩니다.

 

 

제네릭을 사용하는 이유

  1. 타입 안전성: 컴파일 시 타입을 체크하여 타입 관련 오류를 방지할 수 있습니다.
  2. 재사용성: 다양한 타입에 대해 동일한 코드 구조를 사용할 수 있어 코드 중복을 줄일 수 있습니다.
  3. 유연성: 여러 타입을 처리할 수 있어 함수나 클래스의 범용성이 높아집니다.

코틀린의 제네릭을 통해 타입에 구애받지 않는 유연하고 안전한 코드를 작성할 수 있습니다.