Swift中的協(xié)議

1. 協(xié)議語法

protocol SomeProtocol {
    // code
}

要讓自定義類型遵循某個協(xié)議囊卜,在類型名稱后加上協(xié)議名稱即可,中間以冒號(:)分隔栅组,遵循多個協(xié)議時,各協(xié)議之間用逗號(刃麸、)分隔:

struct SomeStruct: FirstProtocol, AnotherProtocol {
    // code
}

擁有父類的類在遵循協(xié)議時司浪,應(yīng)該將父類名放在協(xié)議名之前,以逗號分隔:

class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
    // code
}

2. 屬性要求

protocol SomeProtocol {
    var mustBeSettable: Int { get set } //可讀可寫的變量屬性
    var doesNotNeedToBeSettable: Int { get } //可讀變量屬性
}
protocol AnotherProtocol {
    static var someTypeProperty: Int { get set } //類型屬性吁伺,還可以用class關(guān)鍵字聲明
}

如下所示租谈,這是一個只含有一個實(shí)例屬性要求的協(xié)議。這個協(xié)議表示窟却,任何遵循FullyNamed的類型,都必須有一個可讀的String類型的實(shí)力屬性fullName夸赫。

protocol FullyNamed {
    var fullName: String { get }
}

下面是一個遵循FullyNamed協(xié)議的簡單結(jié)構(gòu)體:

struct Person: FullyNamed {
    var fullName: String
}

let john = Person(fullName: "John Higgins")

下面是一個更為復(fù)雜的類憔足,它適配并遵循了FullyNamed協(xié)議:

class StarShip: FullyNamed {
    var prefix: String?
    var name: String
    init(name: String, prefix: String? = nil) {
        self.name = name
        self.prefix = prefix
    }
    var fullName: String {
        return (prefix != nil ? prefix! + " " : "") + name
    }
}

var ncc1701 = StarShip(name: "Enterprise", prefix: "USS")
print(ncc1701.fullName)
// print "USS Enterprise"

3. 方法要求

protocol SomeProtocol {
    static func someTypeMethod() // 類方法還可以用class關(guān)鍵字修飾
}

下面的例子定義了一個只含有一個實(shí)例方法的協(xié)議:

protocol RandomNumberGenerator {
    func random() -> Double
}

下面的類實(shí)現(xiàn)了一個叫做線性同余生成器的偽隨機(jī)數(shù)算法:

class LinearCongruentialGenerator: RandomNumberGenerator {
    var lastRandom = 42.0
    let m = 139968.0
    let a = 3877.0
    let c = 29573.0
    func random() -> Double {
        lastRandom = (lastRandom * a + c).truncatingRemainder(dividingBy: m)
        return lastRandom / m
    }
}

4. Mutating方法要求

實(shí)現(xiàn)協(xié)議中的mutating方法時,若是類類型控妻,則不用寫mutating關(guān)鍵字揭绑,而對于結(jié)構(gòu)體和枚舉,則必須寫mutating關(guān)鍵字菇存。

protocol Togglable {
    mutating func toggle()
}

enum OnOffSwitch: Togglable {
    case Off, On
    mutating func toggle() {
        switch self {
        case .Off:
            self = .On
        case .On:
            self = .Off
        }
    }
}

var lightSwitch = OnOffSwitch.Off
lightSwitch.toggle() // On

5. 構(gòu)造器要求

protocol SomeProtocol {
    init(someParameter: Int)
}

class SomeClass: SomeProtocol {
    required init(someParameter: Int) {
        // 構(gòu)造器實(shí)現(xiàn)部分
    }
}

如果一個子類重寫了父類的指定構(gòu)造器邦蜜,并且該構(gòu)造器滿足了某個協(xié)議的要求,那么該構(gòu)造器的實(shí)現(xiàn)需要同時標(biāo)注requiredoverride修飾符:

class SomeSuperClass {
    init() {
        // 構(gòu)造器實(shí)現(xiàn)部分
    }
}

class SomeSubClass: SomeSuperClass, SomeProtocol {
    required override init() {
        // 構(gòu)造器實(shí)現(xiàn)部分
    }
}

6. 協(xié)議作為類型

class Dice {
    let sides: Int
    let generator: RandomNumberGenerator
    init(sides: Int, generotor: RandomNumberGenerator) {
        self.sides = sides
        self.generator = generator
    }
    func roll() -> Int {
        return Int(generator.random() * Double(sides)) + 1
    }
}

generator屬性的類型為RandomNumberGenerator贱迟,因此任何遵循了RandomNumberGenerator協(xié)議的類型的實(shí)例都可以賦值給generator絮供,除此之外并無其他要求。

7. 委托(代理)模式

protocol SayHelloDelegate {
    func sayHello(name: String)
}

class ClassA {
    var delegate: SayHelloDelegate?
    var name = "Lucy"
    func play() {
        delegate?.sayHello(name: name)
    }
}

class ClassB: SayHelloDelegate {
    var name = "Lily"
    func sayHello(name: String) {
        print("\(name) 請 \(self.name) 幫她 say Hello")
    }
}

var ca = ClassA()
var cb = ClassB()
ca.delegate = cb
ca.play()
// print "Lucy 請 Lily 幫她 say Hello"

8. 協(xié)議中添加擴(kuò)展

protocol Score {
    var math: Int { get set }
    var english: Int { get set }
    func mathPercent() -> Double
}

struct Puple: Score {
    var math: Int
    var english: Int
    func mathPercent() -> Double {
        return Double(math) / Double(math + english)
    }
}

let p1 = Puple(math: 90, english: 80)
p1.mathPercent() // 0.529

extension Score {
    func mathPercent() -> Double {
        return Double(math) / Double(math + english)
    }
}

struct CollageStudent: Score {
    var math: Int
    var english: Int
}

let c1 = CollageStudent(math: 80, english: 80)
c1.mathPercent() // 0.5

如此缚俏,我們可以不實(shí)現(xiàn)mathPercent方法也能計(jì)算出數(shù)學(xué)所占分?jǐn)?shù)的比例忧换。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末塘揣,一起剝皮案震驚了整個濱河市宿崭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖赞草,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吆鹤,死亡現(xiàn)場離奇詭異,居然都是意外死亡沾凄,警方通過查閱死者的電腦和手機(jī)知允,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來保屯,“玉大人涤垫,你說我怎么就攤上這事∏畜” “怎么了榆芦?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長歧杏。 經(jīng)常有香客問我犬绒,道長,這世上最難降的妖魔是什么凯力? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮拗秘,結(jié)果婚禮上祈惶,老公的妹妹穿的比我還像新娘扮匠。我一直安慰自己凡涩,他們只是感情好活箕,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著克蚂,像睡著了一般筋讨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上版仔,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天蛮粮,我揣著相機(jī)與錄音益缎,去河邊找鬼然想。 笑死,一個胖子當(dāng)著我的面吹牛令哟,可吹牛的內(nèi)容都是我干的妨蛹。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼狠半,長吁一口氣:“原來是場噩夢啊……” “哼颤难!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起行嗤,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤栅屏,失蹤者是張志新(化名)和其女友劉穎堂鲜,沒想到半個月后占婉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體甫恩,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年奖慌,在試婚紗的時候發(fā)現(xiàn)自己被綠了松靡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡岛马,死狀恐怖屠列,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情笛洛,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布沟蔑,位于F島的核電站狱杰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏仿畸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一宣蠕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧甥捺,春花似錦抢蚀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽唱逢。三九已至,卻和暖如春屋休,著一層夾襖步出監(jiān)牢的瞬間坞古,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工劫樟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留痪枫,地道東北人叠艳。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓奶陈,卻偏偏與公主長得像,于是被迫代替她去往敵國和親附较。 傳聞我的和親對象是個殘疾皇子吃粒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容