Swift protocol 系列之 基础介绍
协议是swift中一个非常强大的特性。可以说是与 泛型、函数并称为swift 的三大基石也不为过。
协议
协议是描述一些属性和方法的接口,用于指定特定的类型属性或实例属性。属性要求由“var”关键字声明为属性变量。
protocol NameProtocol { var name: String { get set } var successed: Bool { get } func getName() -> String }复制代码
协议初始化
Swiftng 允许用户以遵循类似于普通类型初始化的方式来初始化协议。如果类来继承协议必须实现协议的初始化方法,并且必须写上的required
关键字。
protocol NameProtocol { init(name: String) } class Person: NameProtocol { required init(name: String) { } }复制代码
协议一致性在所有子类上通过“required”修饰符确保显式或继承实现。当子类覆盖其超类初始化要求时,它由“override”关键字指定。
protocol NameProtocol { init(name: String) } class MainClass { var name: String init(name: String) { self.name = name } } class SubClass: mainClass, NameProtocol { var context: String init(name: String, context : String) { self.context = context super.init(name:name) } required override convenience init(name: String) { self.init(name:name, context:"") } }复制代码
协议组合
Swift 的Hashable
协议继承Equatable
,而Comparable
也继承自Equatable
,这个就有点像我们一个个相同的功能点写成一个个协议。
Swift 还允许我们使用类型别名将两个协议组合在一起,这样就会使协议易于组合而功能明确。就像SwiftCodable
协议正是已这样的方式去实现的。
typealias Codable = Decodable & Encodable复制代码
协议扩展
单写协议方法申明而不去实现,这样也符合协议的要求,但是为这些协议方法提供默认实现是有用的,而且在实际过程中也是很常见的。因为提供协议方法的默认实现和协议属性的默认值,从而使它们“可选”的。这样符合协议的类型可以自己的重新实现或使用默认的实现。而且如果多个类型的实现逻辑是一样的那么使用默认实现可能提炼,而无需单独给每个类型去重复一遍去实现。使用默认行为扩展现有协议的能力非常强大,允许协议增长和扩展,而不必担心破坏现有代码的兼容性。
protocol NameProtocol { func getName() -> String } extension NameProtocol { func getName() { return "name" } }复制代码
同时 Swift 允许我们使用where
关键字将此类条件添加到协议扩展中。这样做可以做到仅为适用于某些情况去实现。
extension NameProtocol where Self: UIViewController { func getName() { return "UIViewController" } }复制代码
上面代码片段中的Self(大写“S”)指的是类型(结构、类或枚举)。通过指定职业就可以只为继承自 UIViewController
的类型扩展协议。
仅限类的协议
有时候你希望能够限制您的协议在类里,以便只有类才能符合它是很有用的。当您想要调用协议方法时:类可以自由地改变它们的变量属性,而结构则不能。在Swift 代码中声明仅类协议的正确方法是使用AnyObject
:
protocol MyProtocol: AnyObject { }复制代码
但是你看别人的以前旧的代码的时候你发现这样的仅限类的协议(这是旧的实现):
protocol MyProtocol: class { }复制代码
协议冲突
protocol P1 { var name: String { get set } func method() //some other methods } protocol P2 { var name: String { get set } func method() //some other methods } extension P1 { func method() { print("Method P1") } } extension P2 { func method() { print("Method P2") } }复制代码
当有一个有一个类型,它符合这两种协议。在这种情况下,我们遇到了不明确的方法或者属性的实现问题。该类型并没有清楚地表明它应该使用哪个协议的方法去实现。这里提供俩个思路:
1、在继承里面自己实现不明确的方法或者属性。
struct Name: P1, P2 { var name: String func method() { print("Method S") } }复制代码
2:将协议作为类型的来操作。
struct Name { var p1: P1 var p2: P2 func method() { _ = p1.name _ = p2.name p1.method() p2.method() } }
作者:icc_tips
链接:https://juejin.cn/post/7031568502435610661