제네릭 매개변수와 인자 (Generic Parameters and Arguments)

선언을 일반화하여 구체적인 타입을 추상화합니다.

이 챕터에서 제네릭 타입, 함수, 이니셜라이저에 대한 매개변수와 인자를 설명합니다. 제네릭 타입, 함수, 서브스크립트, 이니셜라이저를 선언할 때 해당 제네릭 타입, 함수, 이니셜라이저가 동작할 수 있는 타입 매개변수를 지정합니다. 이러한 타입 매개변수는 제네릭 타입의 인스턴스가 생성되거나 제네릭 함수 또는 이니셜라이저가 호출될 때 실제 구체적인 타입 인자에 의해 대체되는 플레이스 홀더 역할을 합니다.

Swift의 제네릭에 대한 개요는 제네릭 (Generics)을 참고바랍니다.

제네릭 매개변수 절 (Generic Parameter Clause)

*제네릭 매개변수 절(generic parameter clause)*은 제네릭 타입이나 함수의 타입 매개변수와 해당 매개변수에 대한 관련 제약조건과 요구사항을 지정합니다. 제네릭 매개변수 절은 꺾쇠 괄호(<>)로 둘러싸여 있고 다음의 형식을 가집니다:

<<#generic parameter list#>>

위 형식의 *제네릭 매개변수 목록(generic parameter list)*은 콤마로 구분된 제네릭 매개변수의 목록이고 각 매개변수는 다음의 형식을 가집니다:

<#type parameter#>: <#constraint#>

제네릭 매개변수는 *타입 매개변수(type parameter)*와 선택 사항인 *제약조건(constraint)*으로 구성됩니다. 위 형식의 *타입 매개변수(type parameter)*는 단순히 플레이스 홀더 타입의 이름입니다 (예를 들어 T, U, V, Key, Value 등). 함수나 이니셜라이저의 시그니처를 포함하여 타입, 함수, 이니셜라이저 선언의 나머지 부분에서 타입 매개변수와 모든 연관 타입에 접근할 수 있습니다.

위 형식의 *제약조건(constraint)*은 타입 매개변수가 특정 클래스를 상속하거나 프로토콜 또는 프로토콜 합성을 준수해야 함을 지정합니다. 예를 들어 아래 제네릭 함수에서 제네릭 매개변수 T: Comparable은 타입 매개변수 T를 대신하는 모든 타입 인자는 Comparable 프로토콜을 준수해야 함을 나타냅니다.

func simpleMax<T: Comparable>(_ x: T, _ y: T) -> T {
    if x < y {
        return y
    }
    return x
}

예를 들어 IntDoubleComparable 프로토콜을 준수하므로 이 함수는 두 타입의 인자를 허용합니다. 제네릭 타입과 다르게 제네릭 함수나 이니셜라이저를 사용할 때는 제네릭 인자 절을 지정하지 않습니다. 대신 타입 인자는 함수나 이니셜라이저에 전달되는 인자의 타입으로부터 추론됩니다.

simpleMax(17, 42) // T is inferred to be Int
simpleMax(3.14159, 2.71828) // T is inferred to be Double

제네릭 Where 절 (Generic Where Clauses)

타입 매개변수와 연관 타입에 요구사항을 추가로 지정하려면 타입이나 함수의 본문의 시작 중괄호 직전에 제네릭 where 절을 포함할 수 있습니다. 제네릭 where 절은 where 키워드로 구성되고 다음에 콤마로 구분된 하나 이상의 *요구사항(requirements)*의 목록으로 구성됩니다.

where <#requirements#>

제네릭 where 절에서 *요구사항(requirements)*은 타입 매개변수가 클래스를 상속하거나 프로토콜 또는 프로토콜 합성을 준수해야 함을 지정합니다. 제네릭 where 절은 타입 매개변수에 대한 간단 제약조건 (예를 들어 <T: Comparable><T> where T: Comparable과 동일)을 표현하는 편의 문법을 제공하지만, 타입 매개변수와 연관 타입에 더 복잡한 제약조건을 제공하기 위해 사용할 수 있습니다. 예를 들어 타입 매개변수의 연관 타입을 프로토콜을 준수하도록 제한할 수 있습니다. 예를 들어 <S: Sequence> where S.Iterator.Element: EquatableSSequence 프로토콜을 준수하고 연관 타입 S.Iterator.ElementEquatable 프로토콜을 준수하도록 지정합니다. 이 제약조건은 시퀀스의 각 요소가 비교 가능함을 보장합니다.

== 연산자를 사용하여 두 타입이 동일하다는 요구사항을 지정할 수도 있습니다. 예를 들어 <S1: Sequence, S2: Sequence> where S1.Iterator.Element == S2.Iterator.ElementS1S2Sequence 프로토콜을 준수하고 두 시퀀스의 요소가 같은 타입이어야 한다는 제약조건을 나타냅니다.

타입 매개변수를 대체하는 모든 타입 인자는 타입 매개변수에 있는 모든 제약조건과 요구사항을 충족해야 합니다.

제네릭 where 절은 타입 매개변수를 포함하는 선언의 일부로 나타나거나 타입 매개변수를 포함하는 선언 내부에 중첩된 선언의 일부로 나타날 수 있습니다. 중첩된 선언에 대한 제네릭 where 절은 둘러싸는 선언의 타입 매개변수를 참조할 수 있습니다; 그러나 where 절의 요구사항은 작성된 선언에만 적용됩니다.

둘러싸는 선언도 where 절을 가지고 있으면, 두 절의 요구사항은 결합됩니다. 아래 예시에서 startsWithZero()ElementSomeProtocolNumeric 모두 준수하는 경우에만 가능합니다.

extension Collection where Element: SomeProtocol {
    func startsWithZero() -> Bool where Element: Numeric {
        return first == .zero
    }
}

타입 매개변수에 다른 제약조건, 요구사항 또는 둘 다 제공하여 제네릭 함수나 이니셜라이저를 오버로드할 수 있습니다. 오버로드된 제네릭 함수나 이니셜라이저를 호출할 때 컴파일러는 이러한 제약조건을 사용하여 호출할 오버로드된 함수나 이니셜라이저를 결정합니다.

제네릭 where 절에 대한 자세한 정보와 제네릭 함수 선언의 예시를 보려면 제네릭 Where 절 (Generic Where Clauses)을 참고바랍니다.

Grammar of a generic parameter clause:

generic-parameter-clause< generic-parameter-list > generic-parameter-listgeneric-parameter | generic-parameter , generic-parameter-list generic-parametertype-name generic-parametertype-name : type-identifier generic-parametertype-name : protocol-composition-type

generic-where-clausewhere requirement-list requirement-listrequirement | requirement , requirement-list requirementconformance-requirement | same-type-requirement

conformance-requirementtype-identifier : type-identifier conformance-requirementtype-identifier : protocol-composition-type same-type-requirementtype-identifier == type

제네릭 인자 절 (Generic Argument Clause)

*제네릭 인자 절(generic argument clause)*은 제네릭 타입의 타입 인자를 지정합니다. 제네릭 인자 절은 꺾쇠 괄호(<>)로 둘러싸여져 있고 다음의 형식을 가집니다:

<<#generic argument list#>>

위 형식의 *제네릭 인자 목록(generic argument list)*은 콤마로 구분된 타입 인자의 목록입니다. *타입 인자(type argument)*는 제네릭 타입의 제네릭 매개변수 절에 있는 해당 타입 매개변수를 대체하는 실제 구체적인 타입의 이름입니다. 그 결과는 해당 제네릭 타입의 특수 버전이 됩니다. 아래 예시는 Swift 표준 라이브러리의 제네릭 딕셔너리 타입의 단순화한 버전을 보여줍니다.

struct Dictionary<Key: Hashable, Value>: Collection, ExpressibleByDictionaryLiteral {
    /* ... */
}

제네릭 Dictionary 타입의 특수한 버전인 Dictionary<String, Int>는 제네릭 매개변수 Key: HashableValue를 구체적인 타입 인자 StringInt로 대체하여 형성됩니다. 각 타입 인자는 제네릭 where 절에 지정된 추가 요구사항을 포함하여 자신이 대체하는 제네릭 매개변수의 모든 제약조건을 충족해야 합니다. 위의 예시에서 Key 타입 매개변수는 Hashable 프로토콜을 준수하도록 제약되므로 StringHashable 프로토콜을 준수해야 합니다.

타입 매개변수 자체를 제네릭 타입의 특수한 버전인 타입 인자로 대체할 수도 있습니다(적절한 제약조건과 요구사항을 충족하는 경우). 예를 들어 Array<Element>의 타입 매개변수 Element를 배열의 특수한 버전인 Array<Int>로 대체하여 요소가 정수인 배열을 형성할 수 있습니다.

let arrayOfArrays: Array<Array<Int>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

제네릭 매개변수 절 (Generic Parameter Clause)에서 언급했듯이 제네릭 함수나 이니셜라이저의 타입 인자로 지정하기 위해 제네릭 인자 절을 사용하지 않습니다.

Grammar of a generic argument clause:

generic-argument-clause< generic-argument-list > generic-argument-listgeneric-argument | generic-argument , generic-argument-list generic-argumenttype

Beta Software:

This documentation contains preliminary information about an API or technology in development. This information is subject to change, and software implemented according to this documentation should be tested with final operating system software.

Learn more about using Apple's beta software.

Last updated

Was this helpful?