스위프트 제네릭
스위프트는 일반 유연성을 제공하고 재사용 가능한 기능과 유형을 작성할 수 있습니다.
스위프트 표준 라이브러리는 일반 코드에 의해 구성된다.
스위프트 배열과 사전 유형은 일반 집합입니다.
당신은 다른 스위프트의 모든 유형이 될 수있는 String 배열, 또는 데이터 배열을 만들 수있는 int 배열을 만들 수 있습니다.
다음 예제에서는 두 값의 교환이 아닌 일반 함수 지능 교환입니다 :
// 定义一个交换两个变量的函数 func exchange(inout a: Int, inout b: Int) { let temp = a a = b b = temp } var numb1 = 100 var numb2 = 200 print("交换前数据: \(numb1) 和 \(numb2)") exchange(&numb1, b: &numb2) print("交换后数据: \(numb1) 和 \(numb2)")
위의 프로그램 실행 출력은 다음과 같습니다
交换前数据: 100 和 200 交换后数据: 200 和 100
범용 기능은 지능 또는 문자열로, 모든 유형에 액세스 할 수 있습니다.
다음의 예는 교환 스왑이 지능과 문자열 값에 대한 일반적인 기능입니다 :
func exchange<T>(inout a: T, inout b: T) { let temp = a a = b b = temp } var numb1 = 100 var numb2 = 200 print("交换前数据: \(numb1) 和 \(numb2)") exchange(&numb1, b: &numb2) print("交换后数据: \(numb1) 和 \(numb2)") var str1 = "A" var str2 = "B" print("交换前数据: \(str1) 和 \(str2)") exchange(&str1, b: &str2) print("交换后数据: \(str1) 和 \(str2)")
위의 프로그램 실행 출력은 다음과 같습니다
交换前数据: 100 和 200 交换后数据: 200 和 100 交换前数据: A 和 B 交换后数据: B 和 A
(일반적으로이 경우 문자 T로 표시) 자리 표시 자 유형 이름을 사용하여이 기능을 대신 (예 : INT, 문자열 또는 두 번으로) 실제 유형 이름의 일반 버전입니다. 자리 표시 자 유형 이름은 어떤 종류의 T를 제안하지해야하지만, 그것은을 제안하고 b는 관계없이 T가 나타내는 종류의, 같은 종류의 T해야합니다. 만 교환 (_ : _ : T가 나타내는 실제 유형을 판별하기 위해 각 통화 유형에 전달 기능.
또 다른 차이점은 자리 표시 자 타입 (T)의 일반적인 이름 뒤에 후자의 기능 이름 (꺾쇠 괄호로 묶여 있다는 것입니다
일반 유형
스위프트는 자신의 일반적인 유형을 정의 할 수있다.
사용자 정의 클래스, 구조체, 및 열거 형은 배열 및 사전 사용 등 모든 유형에 적용.
struct TOS<T> { var items = [T]() mutating func push(item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() } } var tos = TOS<String>() tos.push("Swift") print(tos.items) tos.push("泛型") print(tos.items) tos.push("类型参数") print(tos.items) tos.push("类型参数名") print(tos.items) let deletetos = tos.pop()
위의 프로그램 실행 출력은 다음과 같습니다
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "类型参数"] ["Swift", "泛型", "类型参数", "类型参数名"]
확장 된 제네릭 형식
당신이 (확장 키워드를 사용) 시간의 제네릭 형식을 확장하면 확장 된 정의의 형식 매개 변수 목록을 제공 할 필요가 없습니다. 더 편리하게는리스트 선언 프리미티브 타입 파라미터 타입 정의 사용으로 확장 할 수 있고, 원래의 형태에서 파라미터 이름이 입력 파라미터의 원래의 정의를 기준으로 사용된다는 것이다.
예
다음 예는 제 1 계산라는 판독 전용 속성을 추가, 일반 TOS 유형 확장, 상기 스택 엘리먼트의 현재 정상 리턴 스택으로부터 제거되지 않는다.struct TOS<T> { var items = [T]() mutating func push(item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() } } var tos = TOS<String>() tos.push("Swift") print(tos.items) tos.push("泛型") print(tos.items) tos.push("类型参数") print(tos.items) tos.push("类型参数名") print(tos.items) // 扩展泛型 TOS 类型 extension TOS { var first: T? { return items.isEmpty ? nil : items[items.count - 1] } } if let first = tos.first { print("栈顶部项:\(first)") }
위의 프로그램 실행 출력은 다음과 같습니다
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "类型参数"] ["Swift", "泛型", "类型参数", "类型参数名"] 栈顶部项:类型参数名
형 제약
유형 제약 유형 매개 변수가 지정된 클래스에서 상속 또는 특정 프로토콜 또는 조성물을 준수해야 함을 지정합니다.
형 제약 구문
당신은 유형 매개 변수 체인의 한 부분으로, 콜론으로 구분 유형 매개 변수 이름 뒷면의 형식 제약 조건을 작성할 수 있습니다. (신택스 같은 범용 형)를 다음과 같이 일반적인 기능 제한 구문의 유형에 기초하여 이러한 작용은 :
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) { // 这里是函数主体 }
예
// 函数可以作用于查找一字符串数组中的某个字符串 func findStringIndex(array: [String], _ valueToFind: String) -> Int? { for (index, value) in array.enumerate() { if value == valueToFind { return index } } return nil } let strings = ["cat", "dog", "llama", "parakeet", "terrapin"] if let foundIndex = findStringIndex(strings, "llama") { print("llama 的下标索引值为 \(foundIndex)") }
위의 프로그램 실행 출력은 다음과 같습니다
llama 的下标索引值为 2
연결 유형의 예
스위프트 typealias은 협회의 유형을 설정하는 데 사용되는 키워드.
때로는 하나를 선언 프로토콜을 정의하거나 정의의 프로토콜 부분의 더 많은 관련 유형은 매우 유용하다.
protocol Container { // 定义了一个ItemType关联类型 typealias ItemType mutating func append(item: ItemType) var count: Int { get } subscript(i: Int) -> ItemType { get } } // 遵循Container协议的泛型TOS类型 struct TOS<T>: Container { // original Stack<T> implementation var items = [T]() mutating func push(item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() } // conformance to the Container protocol mutating func append(item: T) { self.push(item) } var count: Int { return items.count } subscript(i: Int) -> T { return items[i] } } var tos = TOS<String>() tos.push("Swift") print(tos.items) tos.push("泛型") print(tos.items) tos.push("参数类型") print(tos.items) tos.push("类型参数名") print(tos.items)
위의 프로그램 실행 출력은 다음과 같습니다
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "参数类型"] ["Swift", "泛型", "参数类型", "类型参数名"]
어디 문
제약 조건의 종류는 제한 일반적인 함수 또는 클래스의 유형의 정의 준수를 보장합니다.
당신은 명령문의 매개 변수를 정의 할 수있는 매개 변수 목록에서 제약.
어디 문이 하나 이상의 협회에 대한 제약의 유형, 뒤에 뒷면의 유형 매개 변수 목록, 다음에 문을 작성할 수 있습니다 (또는) 하나 이상의 유형과 (평등) 관계 사이의 연결 유형에 해당.
예
다음 예는 컨테이너의 두 인스턴스를 같은 순서로 같은 요소가 포함되어 있는지 여부를 확인하는 데 사용 allItemsMatch라는 이름의 일반적인 기능을 정의합니다.
모든 요소가 일치 할 경우, 그렇지 않으면 거짓, 사실의 부울 값으로 돌아갑니다.
protocol Container { typealias ItemType mutating func append(item: ItemType) var count: Int { get } subscript(i: Int) -> ItemType { get } } struct Stack<T>: Container { // original Stack<T> implementation var items = [T]() mutating func push(item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() } // conformance to the Container protocol mutating func append(item: T) { self.push(item) } var count: Int { return items.count } subscript(i: Int) -> T { return items[i] } } func allItemsMatch< C1: Container, C2: Container where C1.ItemType == C2.ItemType, C1.ItemType: Equatable> (someContainer: C1, anotherContainer: C2) -> Bool { // 检查两个Container的元素个数是否相同 if someContainer.count != anotherContainer.count { return false } // 检查两个Container相应位置的元素彼此是否相等 for i in 0..<someContainer.count { if someContainer[i] != anotherContainer[i] { return false } } // 匹配所有项,返回 true return true } var tos = Stack<String>() tos.push("Swift") print(tos.items) tos.push("泛型") print(tos.items) tos.push("Where 语句") print(tos.items) var eos = ["Swift", "泛型", "Where 语句"] print(eos)
위의 프로그램 실행 출력은 다음과 같습니다
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "Where 语句"] ["Swift", "泛型", "Where 语句"]