Swift 基础 Protocol 讲解

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

熟悉 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(someParameterInt)
}

协议作为类型

协议本身只是接口,实际上并不实现任何功能。但协议自身可以作为一种类型使用。它们可以像其他普通类型一样用在函数、方法或构造器中的参数类型或返回值类型,也可以用作常量、变量或属性的类型。

class SomeClass {
    let someProtocol: SomeProtocol

    init(someProtocolSomeProtocol) {
        self.someProtocol = someProtocol
    }
}

协议的继承

协议可以继承一个或多个其他协议,并且可以在继承的基础上添加新的要求。

protocol InheritingProtocolSomeProtocolAnotherProtocol {
    // 协议的定义
}

继承其他协议的协议,遵守它的类型必须满足所有协议的要求,比如上边这个例子,遵守 InheritingProtocol 协议的类型必须同时满足 InheritingProtocol + SomeProtocol + AnotherProtocol。

协议的扩展

协议可以通过扩展来提供方法、构造器、下标等的默认实现。这可以让你编写可重用的方法或属性,而不需要在每个遵守协议的类型中都实现一遍。

extension SomeProtocol {
    func someMethod() {
        // 提供默认实现
    }
}

给协议做扩展时要注意几点:

  1. 如果一个遵守协议的类型提供了自己的方法或属性实现,那么它将覆盖协议扩展中的默认实现。

  2. 通过在协议上创建扩展方法,所有符合协议的类型都会自动获得此方法实现,而无需任何额外的修改。

  3. 在协议中声明的方法和在协议扩展中声明的方法区别是,后者无法被继承。

纯类协议

通过将 AnyObject 协议添加到协议的继承列表中,可以将协议限制为仅类类型(而不是结构或枚举)。

protocol SomeClassOnlyProtocolAnyObjectSomeInheritedProtocol {
    // 这个协议因为继承了 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 协议是一种强大的特性,它们允许我们编写出更加灵活和可重用的代码。通过定义一组方法和属性的蓝图,我们可以编写出更加通用的代码,这些代码可以被不同的类型实现,而不需要关心这些类型的具体实现细节。同时,协议的继承和扩展使得我们可以创建更加复杂和强大的抽象。

这里每天分享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 “iOS新知”,每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

注册登录 后评论
    // 作者
    iOS新知 发布于 掘金
    • 0
    // 本帖子
    分类
    // 相关帖子
    Coming soon...
    • 0
    Swift 基础 Protocol 讲解iOS新知 发布于 掘金