프로그래밍시니어 iOS 개발자

Swift에서 제너릭 메커니즘을 설명하십시오. 제너릭 타입을 사용할 때 type safety를 보장하려면 어떻게 해야 합니까? 제너릭 타입의 한정 예를 제시하십시오.

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

답변.

제너릭(제너릭 타입)은 유연하고 재사용 가능한 함수 및 타입을 정의할 수 있게 해줍니다. Swift의 주요 특징은 type safety을 유지하는 것으로, 컴파일러가 컴파일 중에 특정 타입과의 작업을 검증합니다. 제너릭 타입은 where 조건, 프로토콜 상속 및 이들의 조합을 통해 제한할 수 있습니다.

코드 예제:

func swapValues<T>(_ a: inout T, _ b: inout T) { let temp = a a = b b = temp } protocol Drawable { func draw() } func drawAll<T: Drawable>(_ items: [T]) { for item in items { item.draw() } } // 프로토콜과 where 조건에 의한 제한 func compareValues<T: Equatable>(_ a: T, _ b: T) -> Bool { return a == b }

함정 질문.

제너릭 함수가 오버로드된 함수 역할을 할 수 있습니까? 컴파일러는 필요한 구현을 어떻게 선택합니까?

답변: 네, 제너릭 함수는 일반 함수 및 다른 제너릭 함수와 함께 오버로드될 수 있습니다. 컴파일러는 가장 구체적인 구현을 선택하려고 합니다. 예:

func printValue(_ value: Int) { print("Int: \(value)") } func printValue<T>(_ value: T) { print("Generic: \(value)") } printValue(5) // Int: 5 printValue("Swift") // Generic: Swift

주제에 대한 미세한 차이로 인한 실제 오류의 예.


이야기

팀은 인덱스를 찾기 위해 배열의 제너릭 확장을 작성했으나, Equatable을 통해 타입을 제한하는 것을 잊었습니다. 이로 인해 Equatable이 아닌 요소가 있는 배열에서 확장을 적용하려 할 때 컴파일 오류가 발생했습니다.


이야기

프로젝트에서 타입 제한 없이 제너릭 객체의 캐시를 구현하려고 했습니다. 그 결과, 런타임에서 다운캐스트 할 때 크래시가 발생했습니다 — 실제 안전한 사용은 associated type과 제약 조건을 가진 프로토콜을 통해 달성될 수 있었습니다.


이야기

개발자들이 제너릭 클래스를 구현했지만, 상속 및 오버라이드 시 자식의 전체 제너릭 매개변수를 지정해야 하는 것을 잊었습니다. 이로 인해 코드는 컴파일되지 않았고 타입 계층을 완전히 재구성해야 했습니다.