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中的泛型是通过对元数据的处理实现的。
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)
1、解决方案2:使用some关键字声明一个不透明类型
- func getObject(_ type: Int) -> some Runnable {
- return Car()
- }
2、some限制只能返回一种类型
1、some除了用在返回值类型上,一般还可以用在属性类型上
- protocol Runnable {
- associatedtype Speed
- }
-
- class Dog: Runnable {
- typealias Speed = Double
- }
-
- class Person {
- var pet: some Runnable {
- return Dog()
- }
- }