協(xié)議擎勘,可以理解為一個類型霉涨,協(xié)議跟繼承有點像
協(xié)議钥勋,就是規(guī)定一個東西應(yīng)該有那些屬性,有哪些方法
我們可以先定義一個協(xié)議
protocol Pet{//協(xié)議里邊不能用let
var name:String {set get}//可讀可寫的屬性
var age:Int {get}
func playWith()//協(xié)議里邊科阎,只寫方法定義
func init(name:String)//構(gòu)造方法
func fed(food:String)//不能默認(rèn)值
}
再來定義一個類(或者結(jié)構(gòu)體等類型)來遵循這個協(xié)議
class Cat:Pet{
private var myName:String?//這個私有變量述吸,是為了寫協(xié)議里邊的計算屬性的set,get方法
required init(name: String) {
self.name = name
}
//這里锣笨,我們用一個計算型屬性來實現(xiàn)協(xié)議里的name屬性蝌矛,如果是可讀可寫的,我么可以簡單的寫上 var name:String错英,就和下邊的是等價的了入撒,如果是get-only的屬性,我們可以let age:Int椭岩,就可以了茅逮,但是璃赡,我們也可以直接用var age:Int,這樣age就是一個可讀可寫的屬性了献雅,這樣是允許的碉考,協(xié)議只規(guī)定了要有一個age,并且包含get方法就行挺身。這一點很重要
var name: String{
set{
myName = newValue
}
get{
return myName ?? "meiyou"
}
}
func playWith() {
}
func fed(food: String) {
}
}
這里侯谁,協(xié)議里邊的方法,默認(rèn)都是required
如果想有可選方法章钾,可以這樣寫
@objc protocol Pet{//協(xié)議里邊不能用let
var name:String { set get }
@objc optional func playWith()//可選方法
func fed(food:String)//不能默認(rèn)值
}
可以看到在protocol里邊良蒸,有一個構(gòu)造方法,那么伍玖,遵循這個協(xié)議的類或者結(jié)構(gòu)體等嫩痰,都需要重寫這個構(gòu)造方法
在Cat這個類里邊,要這樣
//這里窍箍,required表示必須實現(xiàn)串纺,如果Cat還有子類,那么子類也必須寫init方法
required init(name: String) {
}
如果Cat這樣寫
final class Cat:Pet{
那么init方法就不需要required了椰棘,因為我們已經(jīng)聲明了這個類不可以被繼承
我們來提一下泛型
試想一下我們有這么一個方法纺棺,交換兩個對象,可以是整型邪狞,可以是字符串祷蝌,可以是Double等等,當(dāng)然我們可以寫三個函數(shù)帆卓,函數(shù)名是一樣的巨朦,只是參數(shù)不一樣,也就是用到函數(shù)的重載剑令,這樣就會有很多重復(fù)的邏輯糊啡,我們可以寫一個這樣的函數(shù)
func exchange<R>(a:inout R, b: inout R){//這里,R是一個自己定義的吁津,一般我們寫的是T棚蓄,系統(tǒng)也是用的T
(a,b) = (b,a)//這里利用元組來實現(xiàn)交換
}
其實系統(tǒng)的很多都是泛型類型的,典型的有Array碍脏, Dictionary梭依,Set等容器類型的都是泛型類型
我們再來說一下協(xié)議里邊別名的用法(associatedtype, typealias)
protocol Weight{
associatedtype weightType//關(guān)聯(lián)一個類型,這里典尾,就相當(dāng)于是定義了一個類型役拴,可以理解為是一個泛型
var weight:weightType{ get }
}
用的時候,可以自定義weightType的類型急黎,比如這樣
class iPhone6s:Weight{
typealias weightType = Double//給協(xié)議里的泛型指定一個具體類型
var weight: weightType{
return 123.123
}
}
let iphone = iPhone6s()
iphone.weight