프로그래밍코틀린 개발자

코틀린에서 타입 추론은 어떻게 작동하나요? 컴파일러가 자동으로 타입을 결정할 수 있는 경우, 제한 사항은 무엇이며, 어떤 경우에 명시적인 타입 지정을 요구하나요?

Hintsage AI 어시스턴트로 면접 통과

답변.

질문의 역사

코틀린은 원래 자바의 안전하고 간결한 대안으로 설계되었습니다. 그의 강력한 특징 중 하나는 타입 추론 메커니즘으로, 이는 타이핑 손실 없이 더 적은 단어로 코드를 작성할 수 있게 해줍니다. 타입 추론은 함수형 언어(예: 스칼라 및 해스켈)와 현대의 정적 타입 언어 설계 트렌드에 영감을 받았습니다.

문제

자바 및 기타 정적 언어에서는 타입을 명시적으로 지정해야 하므로 코드가 과다하게 됩니다. 그러나 명시적 타입이 없으면 코드 이해가 어려워지고 타입 추론이 제대로 작동하지 않을 경우 불명확한 오류로 이어질 수 있습니다.

해결책

코틀린에서는 컴파일러가 종종 문맥에 따라 변수나 표현식의 타입을 스스로 결정할 수 있습니다. 이는 변수, 함수의 반환 값 및 람다 표현식 내부에서 작동합니다. 그러나 명시적 타입 지정을 요구하는 상황도 있습니다. 예를 들어 클래스 내에서 반환 값이 없는 함수 선언('fun doSomething()')을 할 때나 표현식이 모호한 경우입니다.

코드 예시:

val a = 42 // Int val s = "hello" // String fun sum(x: Int, y: Int) = x + y // 반환 타입 Int가 자동으로 추론됨 val list = listOf(1, 2, 3) // List<Int> // 값이 추론될 수 없는 경우 명시적 타입 지정이 필요함 val emptyList: List<String> = emptyList() // 그렇지 않으면 List<Nothing>이 됨

주요 특징:

  • 타입은 로컬 변수, 속성, 함수의 반환 값에 대해 추론됩니다.
  • 문맥이 없거나 모호할 때 명시적 타입 지정을 요구합니다.
  • 람다 표현식의 타입은 람다를 받는 함수의 시그니처에 따라 추론할 수 있습니다.

헷갈릴 수 있는 질문들.

왜 클래스의 속성에 대해 콜론 뒤에 타입을 항상 생략할 수 없나요?

선언 위치에서 초기화되지 않는 속성(예: 게터를 통해 또는 init 블록에서)의 경우, 컴파일러는 초기화자를 볼 수 없기 때문에 타입을 자동으로 추론할 수 없습니다.

class User { val fullName: String // 반드시 타입을 명시해야 하며, 그렇지 않으면 오류 get() = "name" }

명시적인 타입 없이 emptyList()를 사용하면 변수의 타입은 무엇인가요?

이 경우 List<Nothing> 타입이 추론되어 결과는 거의 유용하지 않게 됩니다.

val list = emptyList() // List<Nothing>

함수의 파라미터에 대해 타입 추론이 작동하지 않는 경우는 언제인가요?

함수의 시그니처에서는 항상 파라미터 타입을 명시해야 하며, 그렇지 않으면 컴파일러는 오류를 발생시킵니다.

// 오류: // fun foo(x) = x * 2 // 올바른 경우: fun foo(x: Int) = x * 2

일반적인 오류 및 안티 패턴

  • 빈 컬렉션(emptyList, emptyMap)에 대한 명시적 타입 없음
  • 상속 및 제네릭 타입에 대한 타입 추론의 작동 방식에 대한 이해 부족
  • 타입 추론에 대한 전적인 의존으로 코드 가독성이 저하됨

실제 사례

부정적인 사례

개발자가 명시적 타입을 지정하지 않고 API 함수에서 값을 반환하기 위해 emptyList()를 사용합니다. 그 결과 List<Nothing> 타입이 되어 이 API와 작업할 때 문제가 발생합니다.

장점:

  • 코드 감소 및 간결성 단점:
  • 타입화 손실, 컴파일 타임에 예기치 않은 오류 가능성

긍정적인 사례

개발자는 빈 컬렉션 작업 시 항상 명시적 타입을 지정하고, 이를 통해 가독성이 향상될 수 있는 경우에만 그러하며, 그렇지 않은 경우에는 컴파일러의 타입 추론에 의존합니다.

장점:

  • 코드가 간결하고 안전함
  • 엄격한 타입화 유지 단점:
  • 타입을 추론할 수 있는 곳에서 명시적으로 지정할 경우 코드가 다소 과중하게 보일 수 있음