이 글은 기존 운영했던 WordPress 블로그인 PyxisPub: Development Life (pyxispub.uzuki.live) 에서 가져온 글 입니다. 모든 글을 가져오지는 않으며, 작성 시점과 현재 시점에는 차이가 많이 존재합니다.
작성 시점: 2017-09-06
한 가지 상황을 가정해보자.
Person 이란 기존 클래스가 있다고 해보자.
open class Person
그리고 이 Person 클래스를 상속하는 Employee 라는 클래스가 있다고 해보자.
class Employee: Person()
그리고, 한 메소드에서는 Person을 파라미터로 가진다고 해보자.
fun operate(person: Person)
이 파라미터에는 Person, Employee 둘 다 받을 수 있는데, Employee는 Person 의 아류형(Subtype)이기 때문이다.
이번엔 좀 다른 상황이다.
다른 메소드에서 Array 을 파라미터로 가진다고 해보자.
fun operate(person: Array)
\
그러면 오직 Person만 받을 수 있는데, 이는 Array 는 Array의 아류형이 아니기 때문이다.
이렇기 때문에, Invariant types (불변 유형) 란 개념이 나온다.
Employee 가 Person의 아류형이라도, Array 는 Array 의 아류형이 아니고, Array 는 Array 의 아류형이 아니면 불변 유형이라 정한다.
사실, 자바의 모든 클래스는 불변형이다. 그렇기에 말도 안되는 상황이 나올 수 있다.
Employee 는 Person 의 아류형인데, 왜 제너릭으로는 넘기지 못하지?
Effective Java, item 28번 Use bounded wild cards to increase API flexibility 에 문제가 잘 설명되어 있다.
위에서 설명한 대로, 자바의 모든 클래스는 불변형이기에 제너릭에서는 상속 관계의 클래스를 넘기지 못한다.
그래서 자바에는 이런 문제를 해결하기 위해서 와일드카드를 사용하여, <? extends E> 식으로 제너릭으로 넘기도록 처리했다.
? extends E 라고 선언함으로써 E 자체가 아닌, E 또는 E의 일부 하위 유형을 수집할 수 있게 한다. 이럼으로서 extends 상한 값이 있는 와일드 카드는 공변성을 생성할 수 있는 것이다.
조슈아는 '최대한의 유연성을 위해 producers 또는 consumers 를 대변하는 인풋 파라미터에서 와일드카드 유형을 사용하라' 라고 추천하면서 PECS 라는 연상 기호를 제안했는데, Producer-Extends, Consumer-Super 라는 뜻이다.
그럼 다음 글 부터, 코틀린은 이를 어떻게 해결하는지 살펴보자.