泛型(Generics)
泛型可以将类型参数化,提高代码复用率,减少代码量
func swapValues
(a, b) = (b, a)
}
var i1 = 10
var i2 = 20
swapValues(&i1, &i2)
var d1 = 10.0
var d2 = 20.0
swapValues(&d1, &d2)
struct Date {
var year = 0, month = 0, day = 0
}
var dd1 = Date(year: 2011, month: 9, day: 10) var dd2 = Date(year: 2012, month: 10, day: 11) swapValues(&dd1, &dd2)
-------------
func test
泛型
class Stack
var elements = [E]()
func push(_ element: E) { elements.append(element) }
func pop() -> E { elements.removeLast() }
func top() -> E { elements.last! }
func size() -> Int { elements.count }
}
class SubStack
------------------
struct Stack
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 }
}
var stack = Stack
stack.push(11)
stack.push(22)
stack.push(33)
print(stack.top()) // 33
print(stack.pop()) // 33
print(stack.pop()) // 22
print(stack.pop()) // 11
print(stack.size()) // 0
-------------------
enum Score
case point(T)
case grade(String)
}
let score0 = Score
let score2 = Score.point(99.5) let score3 = Score
关联类型(Associated Type)
关联类型的作用:给协议中用到的类型定义一个占位名称
协议中可以拥有多个关联类型
protocol Stackable {
associatedtype Element // 关联类型
mutating func push(_ element: Element)
mutating func pop() -> Element
func top() -> Element
func size() -> Int
}
------------------------
class Stack
// typealias Element = E
var elements = [E]()
func push(_ element: E) {
elements.append(element) }
func pop() -> E { elements.removeLast() }
func top() -> E { elements.last! }
func size() -> Int { elements.count }
}
-----------------------------
class StringStack : Stackable {
// 给关联类型设定真实类型
// typealias Element = String
var elements = [String]()
func push(_ element: String) { elements.append(element) }
func pop() -> String { elements.removeLast() }
func top() -> String { elements.last! }
func size() -> Int { elements.count } }
var ss = StringStack()
ss.push("Jack")
ss.push("Rose")
类型约束
protocol Runnable { }
class Person { }
func swapValues
(a, b) = (b, a)
}
-----------
protocol Stackable {
associatedtype Element: Equatable
}
class Stack
------
func equal
return false
}
-----------
var stack1 = Stack
var stack2 = Stack
// error: requires the types 'Int' and 'String' be equivalent equal(stack1, stack2)
协议类型的注意点
protocol Runnable {}
class Person : Runnable {}
class Car : Runnable {}
func get(_ type: Int) -> Runnable { if type == 0 {
return Person()
}
return Car()
}
var r1 = get(0)
var r2 = get(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 }
}
泛型解决
解决方案1:使用泛型
func get
if type == 0 {
return Person() as! T
}
return Car() as! T
}
var r1: Person = get(0)
var r2: Car = get(1)
不透明类型(Opaque Type)
解决方案2:使用some关键字声明一个不透明类型
some限制只能返回一种类型
func get(_ type: Int) -> some Runnable { Car() }
var r1 = get(0)
var r2 = get(1)
some
some除了用在返回值类型上,一般还可以用在属性类型上
protocol Runnable { associatedtype Speed }
class Dog : Runnable { typealias Speed = Double }
class Person {
var pet: some Runnable {
return Dog()
} }
可选项的本质
可选项的本质是enum类型
public enum Optional
case none
case some(Wrapped)
public init(_ some: Wrapped) }
------------
var age: Int? = .none
age = 10
age = .some(20)
age = nil
-----------
var age: Int? = 10
var age0: Optional
var age2 = Optional.some(10)
var age3 = Optional(10)
age = nil
age3 = .none
---------
switch age {
case let v?:
print("some", v)
case nil:
print("none")
}
switch age {
case let .some(v):
print("some", v)
case .none:
print("none")
}
---------
var age: Int? = nil
var age0 = Optional
var age1: Optional
----------
var age_: Int? = 10
var age: Int?? = age_
age = nil
var age0 = Optional.some(Optional.some(10)) age0 = .none
var age1: Optional
------------
var age: Int?? = 10
var age0: Optional