协议基础

关于协议

协议指定符合协议的 Swift 对象类型(类,结构或枚举)所需的初始化程序,属性,函数,下标和关联类型。在某些语言中,后续对象的需求规范的类似想法被称为接口

声明和定义的协议是一个类型本身,具有其声明要求的签名,有点类似于 Swift 函数是基于其参数和返回的签名的类型的方式。

Swift 协议规范可以是可选的,明确要求和/或通过称为协议扩展的工具给定默认实现。Swift 对象类型(类,结构或枚举)希望符合使用 Extensions 满足其所有指定要求的协议,只需说明其符合完全一致性的要求。Protocol Extensions 的默认实现工具足以履行符合协议的所有义务。

协议可以由其他协议继承。这与 Protocol Extensions 结合使用,意味着 Protocols 可以而且应该被认为是 Swift 的一个重要特性。

协议和扩展对于实现 Swift 更广泛的程序设计灵活性和开发过程的目标和方法非常重要。Swift 的协议和扩展功能的主要目的是促进程序架构和开发中的组合设计。这被称为面向协议的编程。坚硬的老计时器认为这优于对 OOP 设计的关注。

协议定义了可以由任何结构枚举实现的接口 :

protocol MyProtocol {
    init(value: Int)                      // required initializer
    func doSomething() -> Bool            // instance method
    var message: String { get }           // instance read-only property
    var value: Int { get set }            // read-write instance property
    subscript(index: Int) -> Int { get }  // instance subscript
    static func instructions() -> String  // static method
    static var max: Int { get }           // static read-only property
    static var total: Int { get set }     // read-write static property
}

协议中定义的属性必须注释为 { get }{ get set }{ get } 意味着该属性必须是 gettable,因此它可以实现为任何类型的属性。{ get set } 意味着该属性必须既可以设定也可以获得。

结构,类或枚举可以符合协议:

struct MyStruct : MyProtocol {
    // Implement the protocol's requirements here
}
class MyClass : MyProtocol {
    // Implement the protocol's requirements here
}
enum MyEnum : MyProtocol {
    case caseA, caseB, caseC
    // Implement the protocol's requirements here
}

协议还可以通过扩展来定义其任何需求的默认实现

extension MyProtocol {
    
    // default implementation of doSomething() -> Bool
    // conforming types will use this implementation if they don't define their own
    func doSomething() -> Bool {
        print("do something!")
        return true
    }
}

协议可以用作类型,只要它没有 associatedtype 要求

func doStuff(object: MyProtocol) {
    // All of MyProtocol's requirements are available on the object
    print(object.message)
    print(object.doSomething())
}

let items : [MyProtocol] = [MyStruct(), MyClass(), MyEnum.caseA]

你还可以定义符合多个协议的抽象类型 :

Version >= 3.0

使用 Swift 3 或更高版本,可以通过使用&符号(&)分离协议列表来完成:

func doStuff(object: MyProtocol & AnotherProtocol) {
    // ...
}

let items : [MyProtocol & AnotherProtocol] = [MyStruct(), MyClass(), MyEnum.caseA]

Version < 3.0

旧版本具有语法 protocol<...>,其中协议是尖括号 <> 之间的逗号分隔列表。

protocol AnotherProtocol {
    func doSomethingElse()
}

func doStuff(object: protocol<MyProtocol, AnotherProtocol>) {
    
    // All of MyProtocol & AnotherProtocol's requirements are available on the object
    print(object.message)
    object.doSomethingElse()
}

// MyStruct, MyClass & MyEnum must now conform to both MyProtocol & AnotherProtocol
let items : [protocol<MyProtocol, AnotherProtocol>] = [MyStruct(), MyClass(), MyEnum.caseA]

可以扩展现有类型以符合协议:

extension String : MyProtocol {
    // Implement any requirements which String doesn't already satisfy
}