extension
- 向已有的
struct、enum、class中添加新功能 - 扩展不能重写已有功能
- 计算型属性
extension Int { var add: Int { return self + 100 } } let addition = 3.add - 构造器和方法
struct sum { var num1 = 100, num2 = 200 } extension sum { // 添加方法 func updateTemp() { } // 添加可变实例方法 mutating func update() { self.num1 = 300 } // 添加新的构造器 init(x: Int, y: Int) { self.num1 = x self.num2 = y } // 添加下标方法 subscript(multtable: Int) -> Int { return 100 } } - 嵌套类型
extension Int { enum calc { case add case sub } var print: calc { switch self { case 0: return .add case 1: return .sub default: return .add } } } print(3.print)
protocol
- 协议规定了用来实现某一特定功能所必需的方法和属性
protocol中必须指明get和set,只读属性用{get}enum days { case sun,mon,tue } protocol daysOfWeak { var mark: Int {get set} var result: Bool { get} // 在方法中,改变值类型实例 mutating func show() }required: 可以保证所有遵循该协议的子类,同样能为构造器提供一个现实的实现或者继承实现protocol tcpProtocol { init(no: Int) } class mainClass { var no: Int init(no: Int) { self.no = no } } class subClass: mainClass,tcpProtocol { var no2: Int init(no: Int, no2: Int) { self.no2 = no super.init(no: no) } //因为遵循协议,所以需要require, 因为继承自父类,所以需要override required override convenience init(no: Int) { self.init(no: no, no2: 2) } }protocol可以被当做类型来使用- 在
extension中实现protocolprotocol tcpProtocol { func ageType() -> String } class mainClass { } extension mainClass: tcpProtocol { func ageType() -> String { return "" } } - 协议可以继承一个或者多个协议
class专属协议- 通过
class关键字,限制协议只能适配到class类型中 class关键字,必须出现在协议的继承列表中的第一个
protocol tcpProtocol: class { func ageType() -> String }- 通过
- 协议合成
,和&遵循多个协议时的分隔符protocol Stname { var name: String {get} } protocol Stage { var age: Int {get} } struct Person: Stname, Stage { var name: String var age: Int } // celebrator 同时遵循Stage和Stname func show(celebrator: Stage & Stname) { print("\(celebrator.age) + \(celebrator.name)") }
- 检查是否遵循协议
as?
let per = Person(name: "1", age: 0) // 检查实例是否遵循了某个协议。 if per is Stage { print("per confirm to Stage") } // 当遵循该协议时返回该协议,否则返回nil if let obj = per as? Stage { print("per confirm to Stage") }
泛型
- 泛型使用占位类型名(
<T>), 来代替实际类型,从而避免重复编写代码 - 函数名后面跟着占位类型名
(T),并且用尖括号括起来<T> <T>中的尖括号告诉swift那个T是函数定义的占位类型名,swift不会去查找名为T的实际类型名func swapTwoValues<T>(_ a: inout T, _ b: inout T) { let temp = a a = b b = temp } var num = "123" var num2 = "78" swapTwoValues(&num2, &num) print("\(num) + \(num2)") // 输出78 + 123- 定一个泛型栈
struct Stack<T> { var items = [T]() mutating func push(_ item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() } } // 原始类型定义中声明的类型参数列表在扩展中可以使用 extension Stack { var topItem: T? { return items.isEmpty ? nil : items[items.count - 1] } } - 类型约束
- 指定了一个必须继承自指定类的类型参数,或者遵循一个特定的协议
func findIndex<T: SomeClass, U: SomeClass>(index: T, array: U) { } associatedtype- 关联类型使用关键字
associatedtype来定义protocol Container { associatedtype ItemType mutating func append(_ item: ItemType) var count: Int { get } subscript(i: Int) -> ItemType { get } } struct Stack<T>: Container { typealias ItemType = T var items = [T]() mutating func push(_ item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() } // Container 协议的实现 mutating func append(_ item: T) { self.push(item) } var count: Int { return items.count } subscript(i: Int) -> T { return items[i] } } - 在参数列表中,通过
where附加定义参数的约束extension Array: Container { } // 在参数列表中,通过where附加定义参数的约束 func allItemMatch<C: Container, C2: Container>(_ someC: C, _ anotherC: C2) -> Bool where C.ItemType == C2.ItemType, C.ItemType: Equatable { if someC.count != anotherC.count { return false } for i in 0..<someC.count { if someC[i] != anotherC[i] { return false } } return true }
- 关联类型使用关键字
访问控制
publicopen- 只能修饰
class,访问权限最高 - 能在当前模块内被继承,也能在被导入的模块中被继承
- 能在当前模块内被重写,也能在被导入的模块中重写
- 只能修饰
internal- 默认访问限制
- 别人不能访问该模块源文件中的实体
fileprivate- 当前文件内可以访问
private- 只能在当前类访问,离开作用域无法访问
- 子类和属性等访问权限
- 子类访问权限不得高于父类
- 属性、常量、下标访问权限不得高于本类
- 必要构造器的访问级别必须和本类相同
- 协议访问权限
public protocol Container { associatedtype ItemType // 实现append函数的访问级别也要是public mutating func append(_ item: ItemType) }- 类型别名的访问权限小于或者等于它原本的类型