타입 추론은 JVM 세계에서 가장 널리 알려진 Kotlin의 특징이지만, 사용할 때는 몇 가지 위험성이 있으니 조심해야 합니다.
우선 할당 때 inferred 타입은 정확하게 오른쪽에 있는 피연산자에 맞게 설정된다는 것을 기억해야 합니다.
절대로 슈퍼 클래스 또는 인터페이스로 설정되지 않습니다.
open class Animal
class Zebra: Animal()
fun main() {
var animal = Zebra()
animal = Animal() // 오류: Type mismatch
}
일반적인 경우에 위의 문제는 아래처럼 타입을 명시적으로 지정하여 해결 할 수 있기 때문에 크게 문제가 되지 않습니다.
open class Animal
class Zebra: Animal()
fun main() {
var animal: Animal = Zebra()
animal = Animal()
}
하지만 직접 라이브러리(또는 모듈)를 조작할 수 없는 경우에는 이러한 문제를 쉽게 해결할 수 없습니다. 그리고 이러한 경우에 inferred 타입을 노출하면 위험한 일이 발생할 수 있습니다.
아래에 다음과 같은 인터페이스가 있다고 가정해 봅니다.
interface CarFactory {
fun produce(): Car
}
그리고 기본적으로 지정된 값을 아래 처럼 있다고 선언할 수 있습니다.
val DEFAULT_CAR: Car = Fiat126P()
그리고 DEFAULT_CAR가 명시적으로 Car이므로, 따로 필요 없다고 판단되어 아래와 같이 함수의 리턴 타입을 제거했다고 합시다.
interface CarFactory {
fun produce() = DEFAULT_CAR
}
그런데 누군가 DEFAULT_CAR는 타입 추론에 의해 자동으로 타입이 지정될 것이므로, Car를 명시적으로 지정하지 않아도 된다고 생각하여 이를 제거할 수 있습니다.
val DEFAULT_CAR = Fiat126P()
이제 CarFactory에서는 Fiat126P 이외의 자동차는 생산하지 못합니다.
만약 interface를 우리가 만들었다면 쉽게 해결할 수 있겠지만, 만약 외부 API라면 쉽게 해결할 수 없습니다.
리턴 타입은 API를 잘 모르는 사람들에게 전달해 줄 수 있는 중요한 정보입니다. 따라서 리턴 타입은 외부에서 확인할 수 있게 명시적으로 지정해주는게 좋습니다.
- 타입을 확실하게 지정해야 하는 경우에는 명시적으로 타입을 지정해야 합니다.
- 외부 API를 만들 때는 반드시 타입을 지정하고, 특별한 이유와 확실한 확인 없이는 제거하지 않습니다.
'Kotlin' 카테고리의 다른 글
[Effective Kotlin] 7 - 결과 부족이 발생할 경우 null과 Failure를 사용하라 (0) | 2023.03.12 |
---|---|
[Effective Kotlin] 6 - 사용자 정의 오류보다는 표준 오류를 사용하라 (0) | 2023.03.05 |
[Effective Kotlin] 5 - 예외를 활용해 코드에 제한을 걸어라 (0) | 2023.02.25 |
[Effective Kotlin] 3 - 최대한 플랫폼 타입을 사용하지 말라 (0) | 2023.02.12 |
[Effective Kotlin] 2 - 변수의 스코프를 최소화하라 (0) | 2023.02.04 |