「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」。
协议是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()
}
}