다음과 같은 코드를 생각해보자.
fun execIntFunctContainer( funcContainer: FuncContainer<Int> ) {
funcContainer.func(123)
}
class FuncContainer<T>(val func: (input: T?) -> Unit)
val a = FuncContainer({ a: Int? -> print(a)})
execIntFunctContainer( a)
T 라는 타입 매개변수를 갖는 FuncContainer
클래스는 T? 타입의 입력을 받아 아무것도 반환하지 않는 함수를 func라는 속성으로 가진다.
execIntFuncConstainer
는 Int를 타입매개변수로 갖는 FuncContainer
인스턴스를 인자로 받아, 이 인자의 func
를 실행한다.
마지막으로 a
라는 필드에 FuncContainer
의 인스턴스를 만들어, execIntFuncContainer
에 인자로 넘겨 함수를 호출한다. a 를 만들 때 명시적인 타입 매개변수를 정의하진 않았지만 대충 Int
라고 추론하지 않을까 기대를 했다.
하지만 실행하면 아래와 같은 에러가 난다.
error: type mismatch: inferred type is Line_13.FuncContainer<Int?> but Line_13.FuncContainer<Int> was expected
execIntFunctContainer
에는 FuncContainer<Int>
타입의 인자를 넘겨야 하는데 왜 FuncContainer<Int?>
타입의 인자를 넘겼냐고 한다. 즉, 코틀린은 a 의 타입 매개변수를 추론할 때 Int
라고 생각하지 않고 Int?
이라고 생각했나보다.
이 문제를 해결하는 별로 아름답지 않는 방법은 그냥 a 를 선언할 때 명시적으로 타입 매개변수를 주면 된다.
val a = FuncContainer<Int>({ a: Int? -> print(a)})
하지만 별로 마음에 들지 않는다. 이 때엔 만약 FuncContainer
의 타입 매개변수로 nullable type을 허용하지 않는다면, 다음과 같이 non-nullable type인 Any
만 받겠다고 타입 매개변수에 제약을 가하면 된다.
class FuncContainer<T: Any>(val func: (input: T?) -> Unit)