協議,可以理解為一個類型,協議跟繼承有點像
協議,就是規(guī)定一個東西應該有那些屬性,有哪些方法
我們可以先定義一個協議
protocol Pet{//協議里邊不能用let
var name:String {set get}//可讀可寫的屬性
var age:Int {get}
func playWith()//協議里邊,只寫方法定義
func init(name:String)//構造方法
func fed(food:String)//不能默認值
}
再來定義一個類(或者結構體等類型)來遵循這個協議
class Cat:Pet{
private var myName:String?//這個私有變量,是為了寫協議里邊的計算屬性的set,get方法
required init(name: String) {
self.name = name
}
//這里,我們用一個計算型屬性來實現協議里的name屬性,如果是可讀可寫的,我么可以簡單的寫上 var name:String,就和下邊的是等價的了,如果是get-only的屬性,我們可以let age:Int,就可以了,但是,我們也可以直接用var age:Int,這樣age就是一個可讀可寫的屬性了,這樣是允許的,協議只規(guī)定了要有一個age,并且包含get方法就行。這一點很重要
var name: String{
set{
myName = newValue
}
get{
return myName ?? "meiyou"
}
}
func playWith() {
}
func fed(food: String) {
}
}
這里,協議里邊的方法,默認都是required
如果想有可選方法,可以這樣寫
@objc protocol Pet{//協議里邊不能用let
var name:String { set get }
@objc optional func playWith()//可選方法
func fed(food:String)//不能默認值
}
可以看到在protocol里邊,有一個構造方法,那么,遵循這個協議的類或者結構體等,都需要重寫這個構造方法
在Cat這個類里邊,要這樣
//這里,required表示必須實現,如果Cat還有子類,那么子類也必須寫init方法
required init(name: String) {
}
如果Cat這樣寫
final class Cat:Pet{
那么init方法就不需要required了,因為我們已經聲明了這個類不可以被繼承
我們來提一下泛型
試想一下我們有這么一個方法,交換兩個對象,可以是整型,可以是字符串,可以是Double等等,當然我們可以寫三個函數,函數名是一樣的,只是參數不一樣,也就是用到函數的重載,這樣就會有很多重復的邏輯,我們可以寫一個這樣的函數
func exchange<R>(a:inout R, b: inout R){//這里,R是一個自己定義的,一般我們寫的是T,系統也是用的T
(a,b) = (b,a)//這里利用元組來實現交換
}
其實系統的很多都是泛型類型的,典型的有Array, Dictionary,Set等容器類型的都是泛型類型
我們再來說一下協議里邊別名的用法(associatedtype, typealias)
protocol Weight{
associatedtype weightType//關聯一個類型,這里,就相當于是定義了一個類型,可以理解為是一個泛型
var weight:weightType{ get }
}
用的時候,可以自定義weightType的類型,比如這樣
class iPhone6s:Weight{
typealias weightType = Double//給協議里的泛型指定一個具體類型
var weight: weightType{
return 123.123
}
}
let iphone = iPhone6s()
iphone.weight