Protocols 提出 methods, property 等等的需求,本身不需要實作,
實作交由實際要滿足這些要求的對象。
基本宣告與實作對象
protocol MyProtocol {
}
class MyClass: MyProtocol {
}
若有繼承,要將 protocol 放在 superclass 後面。
protocol MyProtocol {
}
class MyClass {
}
class MyClass2: MyClass, MyProtocol {
}
Property 需求
定義 property 時必須要加上 get, set,若是 readonly,只需加上 get。
protocol MyProtocol {
var pro: Int { get set }
var pro2: String { get }
}
class MyClass: MyProtocol {
var pro: Int {
get {
return 123
}
set {
print(newValue)
}
}
var pro2: String {
return "123"
}
}
Methods 需求
protocol MyProtocol {
func myFunc() {
}
}
class MyClass: MyProtocol {
func myFunc() {
print("func")
}
}
若有其他類型的 method,例如 static 或是 mutating,必須在 protocol 先定義。
protocol MyProtocol {
static func myFunc() {
}
mutating func myFunc(para: int) {
}
}
class MyClass: MyProtocol {
static func myFunc() {
}
func myFunc(para: Int) {
}
}
Initializer 需求
在 protocol 可以定義 designated initializer 或是 convenience initializer,
實作對象都必須要加上 required,除非 class 被定義為 final。
protocol MyProtocol {
init(para: Int)
}
class MyClass: MyProtocol {
required init(para: Int) {
}
}
final MyClass: MyProtocol {
init(para: Int) {
}
}
Protocol 類型
Protocol 可以被當作類型,因此可以當作 function 的參數類型或是 array 的 value 類型,
符合 protocol 類型的就是實作的類別。
protocol MyProtocol {
func test()
}
class MyClass: MyProtocol {
func test() {
print("class")
}
}
class MyClass2: MyProtocol {
func test() {
print("class")
}
}
func myFunc(para: MyProtocol) {
para.test()
}
myFunc(para: MyClass())
let array: [MyProtocol] = [MyClass(), MyClass2()]
Delegation
可以使用 protocol 來實現 delegation 的 design pattern。
protocol MyProtocol {
func willStart()
func didStart()
func endStart()
}
class MyClass {
var delegate: MyProtocol?
func myFunc() {
delegate?.willStart()
}
}
class MyClass2: MyProtocol {
func willStart() {
}
func didStart() {
}
func endStart() {
}
}
let c = MyClass()
c.delegate = MyClass2()
With Extension
可以在 extension 內實作 protocol。
protocol MyProtocol {
}
class MyClass {
}
extension MyClass: MyProtocol {
}
若類別裡面已經實作了 protocol 的需求,可以在 extension 加上空實作。
protocol MyProtocol {
func myFunc()
}
class MyClass {
func myFunc() {
}
}
extension MyClass: MyProtocol {}
繼承 Protocol
Protocol 之間可以互相繼承。
protocol MyProtocol {
func myFunc()
}
protocol MyProtocol2: MyProtocol {
}
class MyClass: MyProtocol2 {
func myFunc() {
}
}
Class only Protocol
定義此 Protocol 只有 classes 能夠使用。
protocol MyProtocol: class {
}
多種 protocol 類型
將 protocol 當作類型時,可以合併多種的 protocol,使用 & 關鍵字。
protocol MyProtocol {
}
protocol MyProtocol2 {
}
class MyClass: MyProtocol, MyProtocol2 {
}
func myFunc(para: MyProtocol & MyProtocol2) {
}
func myFunc(MyClass())
檢查 protocol
使用 is 跟 as 。
protocol MyProtocol {
}
class MyClass {
}
let c = MyClass()
if let result c as? MyProtocol {
}
Optional 要求
在 protocol 內的要求都必須要實作,但也可以宣告 optional 代表不一定要滿足的要求,
但宣告時前面一定要加上 @objc,意思是與 objc 的 class 互通使用,
因此無法使用在 structure 或是 enumeration 上。
@objc protocol MyProtocol {
@objc func myFunc()
}
class MyClass: MyProtocol {
}
也適用之前提到的 optional chaining。
@objc protocol MyProtocol {
@objc var pro: Int {get}
}
class MyClass {
var delegate: MyProtocol?
}
class MyClass2: MyProtocol {
}
let c = MyClass()
c.delegate = MyClass2()
c.delegate?.pro
在 optionals protocol 中定義 property 的時候只能夠宣告 get,無法使用 set。
Protocol extension
額外在 extension 加上實作。
protocol MyProtocol {
var pro: String { get }
}
extension MyProtocol {
func myFunc() -> String {
return pro
}
}
在 extension 內加上預設實作,若有預設實作,則滿足對象不一定要實作,
若有滿足對象有實作,則會覆蓋掉 extension 預設的實作。
protocol MyProtocol {
var pro: String { get }
}
extension MyProtocol {
var pro: String {
get {
return "123"
}
}
}
class MyClass: MyProtocol {
var pro: String {
get {
return "456"
}
}
}