더북(TheBook)

여기서 컴파일러 오류가 발생하는 이유는 useBagBag<MyClass> 타입의 인자를 받는데, 실제로는 Bag<MyClassParent>를 넘기기 때문이다. 이 코드가 작동하게 만들려면 T에 대한 반공변성을 선언해야 한다. 하지만 Bag<T> 인터페이스에는 Tout 위치에 있는 get(): T 함수가 있어서 Tin으로 선언할 수 없다. 이런 경우에 사용 지점에서 타입을 제한하는 해법을 쓴다.

fun useBag(bag: Bag<in MyClass>): Boolean {
    // bag으로 작업 수행
    return true
}

이와 반대로 out 변성도 사용 지점에서 선언할 수 있다.

fun createBag(): Bag<out MyClassParent> = BagImpl2()

class BagImpl2 : Bag<MyClass> {
    override fun use(t: MyClass): Boolean = true
    override fun get(): MyClass = MyClass()
}

여기서 in MyClassout MyClassParent를 제약이 가해진 타입으로 생각할 수 있다. in MyClassin 위치에서만 쓰일 수 있는 MyClass의 하위 타입을 뜻하며, out MyClassParentout 위치에서만 쓰일 수 있는 MyClassParent의 하위 타입을 뜻한다. 컴파일러는 이런 제약을 검사한다. in MyClassout MyClassParentMyClassMyClassParent의 타입 프로젝션(type projection)이라고 부른다.

이 장을 시작할 때 언급했던 것처럼 이 장은 코틀린의 개요에 불과하다. 이제부터는 안전한 프로그램이라는 관점에서 코틀린의 다른 특징을 자세히 살펴보겠다.

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