• Swift中关于协议的基础知识和用法
  • 发布于 1个月前
  • 76 热度
    0 评论
  • 柠檬酸
  • 13 粉丝 44 篇博客
  •   
前言
熟悉 Swift 开发的小伙伴对协议肯定非常熟悉了,今天来梳理一下有关 Swift 协议的基础知识和用法,看看有没有你不知道的知识。

协议语法
创建协议的方法与类、结构和枚举非常相似,使用关键字 protocol + 协议名,然后再加一个大括号就行了:
protocol SomeProtocol {
}
协议中定义属性
协议中支持声明属性:
protocol SomeProtocol {
    var mustBeSettable: Int { get set }
    var doesNotNeedToBeSettable: Int { get }
}
标记 get 表示可获取,标记 set 表示可设置。
协议中还可以声明静态变量,以 static 关键字开头:
protocol AnotherProtocol {
    static var someTypeProperty: Int { get set }
}
协议中定义方法
实例方法直接使用 func 关键字就行了:
protocol RandomNumberGenerator {
    func random() -> Double
}
类方法/静态方法需要在 func 前增加 static 关键字:
protocol RandomNumberGenerator {
    static func someTypeMethod()
}
协议中定义 Mutating 方法
值类型的方法需要修改它所属的实例时,需要将 mutating 关键字放在方法 func 的关键字之前,以表示允许该方法修改它所属的实例以及该实例的任何属性:
protocol Togglable {
    mutating func toggle()
}
如果值类型(结构或枚举)实现 Togglable 协议,实现 toggle() 方法时也需要增加 mutating 关键字,类实现这个协议则不用。

协议中定义初始化方法
协议中还可以定义初始化方法:
protocol SomeProtocol {
    init(someParameter: Int)
}
协议作为类型
协议本身只是接口,实际上并不实现任何功能。但协议自身可以作为一种类型使用。它们可以像其他普通类型一样用在函数、方法或构造器中的参数类型或返回值类型,也可以用作常量、变量或属性的类型。
class SomeClass {
    let someProtocol: SomeProtocol
    // 堆代码 duidaima.om
    init(someProtocol: SomeProtocol) {
        self.someProtocol = someProtocol
    }
}
协议的继承
协议可以继承一个或多个其他协议,并且可以在继承的基础上添加新的要求。
protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
    // 协议的定义
}
继承其他协议的协议,遵守它的类型必须满足所有协议的要求,比如上边这个例子,遵守 InheritingProtocol 协议的类型必须同时满足 InheritingProtocol + SomeProtocol + AnotherProtocol。

协议的扩展
协议可以通过扩展来提供方法、构造器、下标等的默认实现。这可以让你编写可重用的方法或属性,而不需要在每个遵守协议的类型中都实现一遍。
extension SomeProtocol {
    func someMethod() {
        // 提供默认实现
    }
}
给协议做扩展时要注意几点:
1.如果一个遵守协议的类型提供了自己的方法或属性实现,那么它将覆盖协议扩展中的默认实现。
2.通过在协议上创建扩展方法,所有符合协议的类型都会自动获得此方法实现,而无需任何额外的修改。
3.在协议中声明的方法和在协议扩展中声明的方法区别是,后者无法被继承。
纯类协议
通过将 AnyObject 协议添加到协议的继承列表中,可以将协议限制为仅类类型(而不是结构或枚举)。
protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
    // 这个协议因为继承了 AnyObject,所以只有类可以遵守
}
向协议扩展添加约束
定义协议扩展时,可以指定符合要求的类型必须满足的约束条件,然后才能使扩展的方法和属性可用。比如,我要求集合协议中的 Element 必须遵守 Equatable 协议,才能使用我扩展出的 allEqual 函数:
extension Collection where Element: Equatable {
    func allEqual() -> Bool {
        for element in self {
            if element != self.first {
                return false
            }
        }
        return true
    }
}
协议中定义可选方法
默认情况下,协议中的属性和方法遵守它的类型必须都实现,但是有些情况可能想让某些方法作为可选实现,通常来说,有两种做法:
1、默认实现
可以使用扩展对某个方法进行默认实现,这样遵守它的类型就可以选择实现或者不实现这个方法了:
extension PrettyTextRepresentable  {
    var prettyTextualDescription: String {
        return textualDescription
    }
}
2、使用 optional 关键字
因为 OC 时代的协议是可以在协议中设置可选方法的,swift 为了能够和 OC 互相调用,把这个特性继承了过来,必须使用 @objc 关键字标记这个协议:
@objc protocol CounterDataSource {
    @objc optional func increment(forCount count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}
使用这个方法的协议必须由类来遵守。

结论
Swift 协议是一种强大的特性,它们允许我们编写出更加灵活和可重用的代码。通过定义一组方法和属性的蓝图,我们可以编写出更加通用的代码,这些代码可以被不同的类型实现,而不需要关心这些类型的具体实现细节。同时,协议的继承和扩展使得我们可以创建更加复杂和强大的抽象。
用户评论