Kotlin 가변성
Kotlin 가변성
- 불변성 : 제너릭이 설정된 객체의 주소 값을 같은 타입의 제네릭이 설정된 변수에만 담을 수 있다.
- 공변성 : 제네릭이 설정된 객채의 주소 값을 부모 클래스 타입의 제네릭이 설정된 변수에도 담을 수 있다.
- 반 공변성 : 제네릭이 설정된 객체의 주소 값을 자식 클래스 타입의 제네릭이 설정된 변수에도 담을 수 있다.
불변성(무변성)
불변성 (Invariant): 기본적으로 제네릭 타입은 불변성입니다. 불변성은 타입 간에 하위 타입 관계가 없음을 의미합니다. 즉, List<String>은 List<Any>의 하위 타입도 상위 타입도 아닙니다. 이는 제네릭 타입이 완전히 독립적으로 동작하고 서로 호환되지 않는 것을 의미합니다.
fun main() {
var obj1:TestClass1<SubClass1> = TestClass1<SubClass1>()
var obj2:TestClass1<SubClass2> = TestClass1<SubClass1>() // ERROR
}
open class SuperClass1
open class SubClass1 : SuperClass1()
class SubClass2 : SubClass1()
class TestClass1<T>()
Kotlin: Type mismatch: inferred type is SubClass1 but SubClass2 was expected
Kotlin: Type mismatch: inferred type is TestClass1<SubClass1> but TestClass1<SubClass2> was expected
클래스가 상속 관계 이더라도, 타입에는 하위 관계가 없기 때문에, 동일한 타입을 사용해야 한다. 이러한 오류는 주로 제네릭 클래스나 함수를 다룰 때 발생하며, 기대하는 제네릭 타입 매개변수와 다른 타입의 값을 할당하려고 할 때 발생한다.
공변성
공변성은 제네릭 타입이 상속 관계에서 타입 변환을 지원하는 개념입니다. out 키워드를 사용하여 제네릭 타입 매개변수를 공변성으로 지정할 수 있습니다. 예를 들어, List<out T>는 T의 하위 타입인 U에 대해 List<U>의 하위 타입이 될 수 있습니다. 이는 제네릭 타입이 반환 타입으로만 사용되고 입력으로 사용되지 않는 경우 유용합니다.
fun main() {
var obj1:TestClass1<SubClass1> = TestClass1<SubClass1>()
var obj3:TestClass1<SuperClass1> = TestClass1<SubClass1>()
}
open class SuperClass1
open class SubClass1 : SuperClass1()
class SubClass2 : SubClass1()
class TestClass1<out T>()
out 으로 제네릭을 설정시, 부모클래스 타입으로 하위 클래스 객체를 생성 할 수 있다.
반 공변성
반공변성은 제네릭 타입이 상속 관계에서 타입 변환을 반대로 지원하는 개념입니다. in 키워드를 사용하여 제네릭 타입 매개변수를 반공변성으로 지정할 수 있습니다. 예를 들어, Comparable<in T>는 T의 상위 타입인 U에 대해 Comparable<U>의 상위 타입이 될 수 있습니다. 이는 제네릭 타입이 입력 타입으로만 사용되고 반환 타입으로 사용되지 않는 경우 유용합니다.
fun main() {
var obj1:TestClass1<SubClass1> = TestClass1<SubClass1>()
var obj3:TestClass1<SubClass2> = TestClass1<SubClass1>()
}
open class SuperClass1
open class SubClass1 : SuperClass1()
class SubClass2 : SubClass1()
class TestClass1<in T>()
in 으로 제네릭을 설정시, 자식클래스 타입으로 클래스 객체를 생성 할 수 있다. 공변성 방식은 많이 사용하나, 반 공변성 방식은 위험하기 때문에 잘 사용하지 않는다.
객체를 생성할 때 타입을 결정하는 개념을 제네릭이라고 부르며, 상속관계에 있는 객체를 생성할 때, 타입을 지정할때 in, out 키워드를 사용해서 만들수 있다.
메서드는 동일하고 타입만 다른 메서드를 만들고 싶을 때, 많이 사용한다.
댓글
댓글 쓰기