Swift

协议

本文详细介绍了 Swift 中的协议,包括属性要求、方法要求、初始化器要求、协议作为类型、委托模式以及协议扩展。

协议(Protocols)定义了适合特定任务或功能的方法、属性和其他要求的蓝图。协议可以被类、结构体或枚举采用,以提供这些要求的实际实现。

协议语法

定义协议与定义类、结构体和枚举非常相似:

protocol SomeProtocol {
    // 协议定义写在这里
}

属性要求

协议可以要求遵循它的类型提供具有特定名称和类型的实例属性或类型属性。协议只指定属性的名称和类型,以及它是可读的还是可读写的。

protocol FullyNamed {
    var fullName: String { get }
}

struct Person: FullyNamed {
    var fullName: String
}

let john = Person(fullName: "John Appleseed")
// john.fullName 为 "John Appleseed"

方法要求

协议可以要求遵循它的类型实现特定的实例方法和类型方法。

protocol RandomNumberGenerator {
    func random() -> Double
}

class LinearCongruentialGenerator: RandomNumberGenerator {
    var lastRandom = 42.0
    let m = 139968.0
    let a = 3877.0
    let c = 29573.0
    func random() -> Double {
        lastRandom = ((lastRandom * a) + c).truncatingRemainder(dividingBy: m)
        return lastRandom / m
    }
}

异变方法要求 (Mutating Method Requirements)

如果需要在方法中修改结构体或枚举实例本身,需要在协议方法定义前加上 mutating 关键字。

protocol Togglable {
    mutating func toggle()
}

enum OnOffSwitch: Togglable {
    case off, on
    mutating func toggle() {
        switch self {
        case .off:
            self = .on
        case .on:
            self = .off
        }
    }
}

初始化器要求

协议可以要求遵循它的类型实现特定的初始化器。

protocol SomeProtocol {
    init(someParameter: Int)
}

class SomeClass: SomeProtocol {
    required init(someParameter: Int) {
        // 初始化器实现
    }
}

协议作为类型

尽管协议本身不实现任何功能,但它可以被当作一个完全成熟的类型来使用。例如,可以作为函数参数、返回类型或集合中的元素类型。

class Dice {
    let sides: Int
    let generator: RandomNumberGenerator
    init(sides: Int, generator: RandomNumberGenerator) {
        self.sides = sides
        self.generator = generator
    }
    func roll() -> Int {
        return Int(generator.random() * Double(sides)) + 1
    }
}

委托 (Delegation)

委托是一种设计模式,允许类或结构体将其部分职责移交(或委托)给另一个类型的实例。

protocol DiceGame {
    var dice: Dice { get }
    func play()
}

protocol DiceGameDelegate: AnyObject {
    func gameDidStart(_ game: DiceGame)
    func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
    func gameDidEnd(_ game: DiceGame)
}

协议扩展

可以使用扩展来为协议本身提供方法、初始化器、下标和计算属性的默认实现。这允许你为遵循协议的类型定义行为,而无需在每个类型的实现中重复代码。

extension RandomNumberGenerator {
    func randomBool() -> Bool {
        return random() > 0.5
    }
}
在 GitHub 上编辑

上次更新于