协议用于统一方法和属性的名称,可是协议没有实现,在其它语言中一般叫作接口。html
使用协议的好处程序员
协议的使用步骤编程
Swift 语言中协议的声明使用关键字 protocol
。swift
protocol 协议: 继承的协议1, 继承的协议2 { var 某个属性: 类型 {set get} func 某个方法(参数列表) -> 返回值类型 init 构造器(参数列表) }
1)在协议中加入的属性能够不用实现,也不限制因而计算属性仍是存储属性,可是必需要指出属性的读写权限。数据结构
{set get}
表示可读写,{get}
表示可读。当在实现时为可读属性添加 setter
方法,系统也不会报错,协议中指定的权限只是最低权限。ide
// 定义协议 protocol someProtocol { var num: Int {get} }
class Show: someProtocol { var so = 1 // 实现协议中定义的属性 var num: Int { get { return so } set { so = newValue + 1 } } } var show1 = Show() show1.num = 1 print(show1.num) // 2
2)类、结构体和枚举均可以遵照协议。ui
若是是类遵照了协议,那么协议中的变异方法和普通方法没有区别。code
mutating func 变异方法名()
3)能够在协议的定义中指定某个成员为类型成员,在成员定义前加上关键字 static
便可。htm
protocol someProtocol { // 定义类型成员 static func someTypeNethod() }
4)限制协议仅和类一块儿工做也是可行的,只须要在冒号后面添加一个 class
关键字,这样就表明这个协议只能被类所遵照。对象
protocol 协议: class, 继承的协议1, 继承的协议2 { var 某个属性: 类型 {set get} func 某个方法(参数列表) -> 返回值类型 init 构造器(参数列表) }
Swift 中遵照协议的格式和继承父类同样,把协议名放到类声明的尾部,在继承的后面,以逗号隔开。
一个类只能继承一个父类,可是能够遵照多个协议。
calss 某个类: 父类, 协议1, 协议2, ... {}
协议别名
若是多个协议老是一块儿出现,则可使用 typealias
关键字给多个协议起一个别名,typealias
并不会生成新的协议。
// Swift 3.0 之前 typealias 协议组合别名 = protocol<协议1, 协议2, ...>
// Swift 3.0 之前 typealias 协议组合别名 = 协议1 & 协议2 ...
calss 某个类: 父类, 协议组合别名 {} struct 某个结构体: 协议组合别名 {}
一旦类遵照了这个协议,就必须实现它里面的全部成员,否则没法经过编译,结构体和枚举也是如此。
若是类遵照的协议中声明了构造器,那么遵照协议的类在实现这个构造器的时候必须把构造器声明为 required
,不然根据构造器的继承原则,可能致使子类没有实现该构造器的状况。
Swift 2.0 以后苹果宣称 Swift 是一门 “面向协议编程” 的语言,这是因为 Swift 2.0 中引入了对协议扩展的特性。
能够提早在协议扩展中定义协议的默认实现,不过这些默认实现并不属于协议自己。
定义两个协议 Coder 和 Swifter。
protocol Coder { var haveFun: Bool {get} var ownMoney: Bool {get} } protocol Swifter { var codingLevel: Int {get} }
如今有三个公司的程序员,用三个结构体来表示。
struct CoderFromA: Coder { var haveFun: Bool = false var ownMoney: Bool = false var name: String init(name: String) { self.name = name } } struct CoderFromB: Coder, Swifter { var haveFun: Bool = true var ownMoney: Bool = true var codingLevel: Int = 3 var name: String init(name: String) { self.name = name } } struct CoderFromC: Coder, Swifter { var haveFun: Bool = true var ownMoney: Bool = true var codingLevel: Int = 5 var name: String init(name: String) { self.name = name } }
// 使用 let coderA = CoderFromA(name: "A") print("\(coderA.name) - \(coderA.haveFun) - \(coderA.ownMoney)") // A - false - false let coderB = CoderFromB(name: "B") print("\(coderB.name) - \(coderB.haveFun) - \(coderB.ownMoney) - \(coderB.codingLevel)") // B - true - true - 3 let coderC = CoderFromC(name: "C") print("\(coderC.name) - \(coderC.haveFun) - \(coderC.ownMoney) - \(coderC.codingLevel)") // C - true - true - 5
Coder
。观察上面的代码能够发现 Swift 程序员都是快乐且富有的,所以结构体 CoderFromB
和 CoderFromC
中会有冗余的部分,这是因为不一样的协议间的因果关系形成的,虽然咱们知道这个事实,可是因为规则的关系咱们不得不重复的去赋值 haveFun
和 ownMoney
属性。
如今使用 swift 的协议扩展,形式以下。
// 定义协议 protocol Coder { var haveFun: Bool {get} var ownMoney: Bool {get} } protocol Swifter { var codingLevel: Int {get} } // 定义协议扩展,设置默认值 extension Coder where Self: Swifter { var haveFun: Bool { return true } var ownMoney: Bool { return true } }
// 定义遵照协议的类型 struct CoderFromA: Coder { var haveFun: Bool = false var ownMoney: Bool = false var name: String init(name: String) { self.name = name } } struct CoderFromB: Coder, Swifter { //var haveFun: Bool = true //var ownMoney: Bool = true var codingLevel: Int = 3 var name: String init(name: String) { self.name = name } } struct CoderFromC: Coder, Swifter { //var haveFun: Bool = true //var ownMoney: Bool = true var codingLevel: Int = 5 var name: String init(name: String) { self.name = name } }
// 使用 let coderA = CoderFromA(name: "A") print("\(coderA.name) - \(coderA.haveFun) - \(coderA.ownMoney)") // A - false - false let coderB = CoderFromB(name: "B") print("\(coderB.name) - \(coderB.haveFun) - \(coderB.ownMoney) - \(coderB.codingLevel)") // B - true - true - 3 let coderC = CoderFromC(name: "C") print("\(coderC.name) - \(coderC.haveFun) - \(coderC.ownMoney) - \(coderC.codingLevel)") // C - true - true - 5
where
限定 Coder
协议的遵照者在同时遵照 Swifter
协议的时候能够得到本次扩展中的默认实现。Coder
和 Swifter
时,协议 Coder
中的属性 haveFun
和 ownMoney
会有默认值。haveFun
和 ownMoney
的值以计算属性 get
方法的形式返回。CoderFromB
和 CoderFromC
中 haveFun
和 ownMoney
的声明。在协议的扩展中,除了给协议中定义的方法赋上默认实现外,还能够定义新的方法并赋上默认实现。
1)常规的写法
// 定义协议 protocol SharedString { func methodForOverride() func methodWithoutOverride() }
// 定义协议扩展,实现方法 extension SharedString { func methodForOverride() { print("method For Override") } func methodWithoutOverride() { methodForOverride() } }
// 使用 extension String: SharedString { } // String 上下文 let str1: String = "Hello" str1.methodForOverride() // method For Override str1.methodWithoutOverride() // method For Override // SharedString 上下文 let str2: SharedString = "Hello" str2.methodForOverride() // method For Override str2.methodWithoutOverride() // method For Override
2)如今在遵照协议的时候从新定义方法 methodForOverride
,修改它的实现。
// 定义协议 protocol SharedString { func methodForOverride() func methodWithoutOverride() }
// 定义协议扩展,实现方法 extension SharedString { func methodForOverride() { print("method For Override") } func methodWithoutOverride() { methodForOverride() } }
// 使用 extension String: SharedString { func methodForOverride() { print(self) } } // String 上下文 let str1: String = "Hello" str1.methodForOverride() // Hello str1.methodWithoutOverride() // Hello // SharedString 上下文 let str2: SharedString = "Hello" str2.methodForOverride() // Hello str2.methodWithoutOverride() // Hello
3)如今把方法 methodWithoutOverride
的声明从 SharedString
协议列表中删除,将它变成一个从声明到实现都在协议扩展中的方法。
// 定义协议 protocol SharedString { func methodForOverride() }
// 定义协议扩展,实现方法 extension SharedString { func methodForOverride() { print("method For Override") } func methodWithoutOverride() { methodForOverride() } }
// 使用 extension String: SharedString { func methodForOverride() { print(self) } } // String 上下文 let str1: String = "Hello" str1.methodForOverride() // Hello str1.methodWithoutOverride() // Hello // SharedString 上下文 let str2: SharedString = "Hello" str2.methodForOverride() // Hello str2.methodWithoutOverride() // Hello
String
和 `SharedString
两种上下文中调用方法,结果仍旧是同样的,看起来 String
对协议方法 methodForOverride
的修改是绝对的。4)最后一步,把方法 methodForOverride
从协议列表中列表中删除,如今 SharedString
的声明列表是空的了。
// 定义协议 protocol SharedString { }
// 定义协议扩展,实现方法 extension SharedString { func methodForOverride() { print("method For Override") } func methodWithoutOverride() { methodForOverride() } }
// 使用 extension String: SharedString { func methodForOverride() { print(self) } } // String 上下文 let str1: String = "Hello" str1.methodForOverride() // Hello str1.methodWithoutOverride() // method For Override print("\n") // SharedString 上下文 let str2: SharedString = "Hello" str2.methodForOverride() // method For Override str2.methodWithoutOverride() // method For Override
String
时,methodForOverride
会调用被重写的版本,而未被重写的方法 methodWithoutOverride
会调用协议扩展中默认的版本,而且未被重写的方法内部调用协议中其它方法时得到的也是没有被重写的版本,这就是协议扩展的 “静态特性”。SharedString
时,那么两个方法都会得到默认的版本。where
的做用是限定协议扩展有效的条件,在 where
语句中可使用 Self
关键字来表明协议的遵照者,能够指定遵照者是某个类的子类或者遵照了某个协议。在 Swift 的协议世界中,每一个对象均可能遵照许多协议,而协议自己能够做为一种类型,在使用类型推断时,编译器会把对象推断为对象自己。
好比说上例中,你能够经过指定实例的类型修改上下文。
协议自己能够继承自另外一个协议,固然不能继承自另外一个类,由于协议是不能有具体方法实现的,因此不能继承自类,协议继承自另外一个协议,无非就是多了一个方法定义。
协议也有继承关系,若是想要遵照这个协议,就必须把它继承的协议也所有实现。