728x90
fun main() {
//제네릭을 사용한 클래스의 인스턴스를 만드려면 타입아규먼트를 제공
//val generics = MyGenerics<String>("테스트")
//val generics = MyGenerics("테스트") // 컴파일러가 제네릭 타입이 String 인것을 알기 때문에 생략 가능
//변수의 타입에 제네릭을 사용한 경우
val list1: MutableList<String> = mutableListOf()
//타입아규먼트를 생성자에서 추가
val list2 = mutableListOf<String>()
//스타 프로젝션을 사용
val list3: List<*> = listOf<String>("테스트")
val list4: List<*> = listOf<Int>(1,2,3,4)
}
- 코틀린의 클래스는 자바와 마찬가지로 타입 파라미터를 가질 수 있다.
- 제네릭을 사용한 클래스의 인스턴스를 만들려면, 타입 아규먼트를 제공하면 된다.
- 인자를 통해 타입 추론이 가능한 경우 타입 아규먼트 생략 가능
- 타입 추론이 가능하기 때문에 변수의 타입에 타입 아규먼트를 추가해도 되고 그렇지 않은 경우 타입 아규먼트를 생성자에서 추가해도 된다.
- 안전하게 사용하고 싶은 경우 어떤 타입이든 받을 수 있는 스타 프로젝션을 사용하면 된다.
변성
- 제네릭에서 파라미터화 된 타입이 서로 어떤 관계에 있는지를 설명하는 개념으로 크게 공변성, 반 공변성, 무 공변성으로 나뉜다.
- 이펙티브 자바에선 공변성과 반 공변성을 설명할 때, PECS(Producer-Extends, Consumer-Super) 규칙을 언급한다.
- 공변성은 자바 제네릭의 extends 키워드이고 코틀린에서는 out
- 반 공변성은 자바 제네릭의 super 키워드이고, 코틀린에서는 in
class MyGenerics<out T>(val t: T){
}
class Bag<T>{
fun saveAll(
to: MutableList<in T>,
from: MutableList<T>,
){
to.addAll(from)
}
}
fun main(){
//변성 : 제네릭에서 파라미터화된 타입이 어떤 관계가 있는지를 설명하는것
//PECS : (Producer-Extends, Consumer-Super)
//공변성은 자바 제네릭의 extends, 코틀린에서는 out
//반공변성은 자바 제네릭의 super, 코틀린에서 in
val generics = MyGenerics<String>("테스트")
//MyGeneric<String> 이 MyGeneric<CharSequence> 보다 상위 타입으로 공변성을 사용하여 구현할 수 있다
val charGenerics: MyGenerics<CharSequence> = generics //컴파일 오류 발생
val bag = Bag<String>()
//반공변성 사용 : 제네릭을 소비하는 측이 되므로 반공변성이다(Consumer)
bag.saveAll(mutableListOf<CharSequence>("1", "2"), mutableListOf<String>("3", "4")) //컴파일 오류
//무공변성 : 실제 String은 CharSequence는 계층 구조이지만, 이걸 제네릭화한 mutableList<String>과 mutableList<CharSequence>는 아무 관계가 아닌것
}
- 특정 상황에서 공변성이 필요하므로 공변성 키워드인 out을 통해 해결한다.
- CharSequence가 String의 상위 타입일 때, MyGenerics<CharSequence>가 MyGenerics<String>의 상위 타입이므로 공변성이다.
- 특정 상황에서 반 공변성이 필요하므로 반공변성 키워드인 in을 사용해 상위 타입도 전달받을 수 있도록 한다.
- String이 CharSequnce의 하위 타입일 때, Bag<String>가 Bag<CharSqequnce>의 상위 타입이 되므로 반 공변성이다.
- 기본은 무 공변성으로 in, out 어떤 것도 지정하지 않은 경우
- String은 CharSequence의 하위 타입이지만, MyGeneric<String>은 MyGeneric<CharSequence>와 아무 관계도 아니다
728x90
'실무 프로젝트로 배우는 Kotlin & Spring > 코틀린 고급' 카테고리의 다른 글
| 페어와 구조분해할당 (0) | 2022.10.16 |
|---|---|
| 지연 초기화 (0) | 2022.10.16 |
| 확장 함수 (0) | 2022.10.09 |
| 실드 클래스 (0) | 2022.10.09 |
| 싱글톤과 동반객체 (0) | 2022.10.09 |