Swift泛型Generics淺析講解
泛型(Generics)
1、泛型可以將類型參數化,提高代碼復用率,減少代碼量
func swapValue<T>(_ a: inout T, _ b: inout T) -> Void { (a, b) = (b, a) }
var fn: (inout Int, inout Int) -> () = swapValue
棧
class Stack<E> { var elements = [E]() func push(_ element: E) -> Void { elements.append(element) } func pop() -> E { elements.removeLast() } func top() -> E { elements.last! } func size() -> Int { elements.count } } var intStack = Stack<Int>() var stringStack = Stack<String>() var anyStack = Stack<Any>()
class SubStack<E>: Stack<E> { } struct Stack<E> { var elements = [E]() mutating func push(_ element: E) { elements.append(element) } mutating func pop() -> E { elements.removeLast() } func top() -> E { elements.last! } func size() -> Int { elements.count } }
匯編分析泛型的實現原理
通過匯編我們可以看到兩次調用的swapValues方法的地址是相同的,也就是說是相同的方法,匯編中有關於metadata的信息,所以推測Swift中的泛型是通過對元數據的處理實現的。
關聯類型(Associated Type)
1、關聯類型的作用:給協議中用到的類型定義一個占位名稱
2、協議中可以擁有多個關聯類型
protocol Stackable { associatedtype Element mutating func push(_ element: Element) mutating func pop() -> Element func top() -> Element func size() -> Int }
class StringStack: Stackable { // typealias Element = String 可寫可不寫 var elements = [String]() func push(_ element: String) -> Void { elements.append(element) } func pop() -> String { elements.removeLast() } func top() -> String { elements.last! } func size() -> Int { elements.count } }
類型約束
protocol Runnable {} class Person {} func swapValues<T: Person & Runnable>(_ a: inout T, _ b: inout T) -> Void { (a, b) = (b, a) }
更多的約束
func equal<S1: Stackable, S2: Stackable>(_ s1: S1, _ s2: S2) -> Bool where S1.Element == S2.Element, S1.Element: Hashable { return false }
協議類型的註意點
protocol Runnable {} class Person: Runnable {} class Car: Runnable {} func getObject(_ type: Int) -> Runnable { if type == 0 { return Person() } return Car() } var r1 = getObject(0) var r2 = getObject(1)
1、如果協議中有associatedtype,那麼會有類型識別不瞭的問題,以下代碼會報錯
protocol Runnable { associatedtype Speed var speed: Speed { get } } class Person: Runnable { var speed: Double { 0.0 } } class Car: Runnable { var speed: Int { 0 } } func getObject(_ type: Int) -> Runnable { if type == 0 { return Person() } return Car() }
泛型解決
解決方案1:使用泛型
protocol Runnable { associatedtype Speed var speed: Speed { get } } class Person: Runnable { var speed: Double { 0.0 } } class Car: Runnable { var speed: Int { 0 } } func getObject<T: Runnable>(_ type: Int) -> T { if type == 0 { return Person() as! T } return Car() as! T } var r1: Person = getObject(0) var r2: Car = getObject(1)
不透明類型(Opaque Type)
1、解決方案2:使用some關鍵字聲明一個不透明類型
func getObject(_ type: Int) -> some Runnable { return Car() }
2、some限制隻能返回一種類型
some
1、some除瞭用在返回值類型上,一般還可以用在屬性類型上
protocol Runnable { associatedtype Speed } class Dog: Runnable { typealias Speed = Double } class Person { var pet: some Runnable { return Dog() } }
到此這篇關於Swift泛型Generics淺析講解的文章就介紹到這瞭,更多相關Swift Generics內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!