swift備忘錄之protocols

格式

protocol SomeProtocol {
    // protocol definition goes here
}

如果類有superclass,則將superclass寫在類后,然后接上protocol砾省。

class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {
    // class definition goes here
}

property in protocol

property在protocol中只定義類型和名字,并不規(guī)定是stored property還是computed property。

protocol中的property都是以var定義们拙。

protocol SomeProtocol {
    var mustBeSettable: Int { get set }
    var doesNotNeedToBeSettable: Int { get }
}

如果在protocol中定義為gettable和settable,那么實(shí)現(xiàn)的時候就不能定義成一個constant stored property或者一個read-only property阁吝。如果protocol中定義的是gettable砚婆,那么就實(shí)現(xiàn)的時候可以根據(jù)自己需要決定是否定義成也settable的property。

type property都需要以static關(guān)鍵字定義突勇。

protocol AnotherProtocol {
    static var someTypeProperty: Int { get set }
}

method in protocol

instance method 和 type method都可以在protocol中定義射沟,type method定義的時候需要以static修飾。

// type method
protocol SomeProtocol {
    static func someTypeMethod()
}

// instance method 
protocol RandomNumberGenerator {
    func random() -> Double
}

如果需要在protocol的method中改變instance的值与境,需要用mutating修飾验夯。例如:

protocol Togglable {
    mutating func toggle()
}

如果你把一個protocol instance method標(biāo)記為mutating,則在class中實(shí)現(xiàn)的時候就沒必要加mutating關(guān)鍵字了摔刁,但是enumration和structure還是需要加挥转。例如:

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()
// lightSwitch is now equal to .on

initializer in protocol

定義的格式為:

protocol SomeProtocol {
    init(someParameter: Int)
}

實(shí)現(xiàn)這個protocol的時候,需要在init前加required關(guān)鍵字共屈。

class SomeClass: SomeProtocol {
    required init(someParameter: Int) {
        // initializer implementation goes here
    }
}

由于final修飾的class是不可以被繼承的绑谣,所以final修飾的class在實(shí)現(xiàn)init方法的時候不需要加required。

如果子類在復(fù)寫一個父類的init方法的時候拗引,恰巧這個init是從protocol中實(shí)現(xiàn)的借宵,則需要使用required和override兩個關(guān)鍵字修飾。

protocol SomeProtocol {
    init()
}
 
class SomeSuperClass {
    init() {
        // initializer implementation goes here
    }
}
 
class SomeSubClass: SomeSuperClass, SomeProtocol {
    // "required" from SomeProtocol conformance; "override" from SomeSuperClass
    required override init() {
        // initializer implementation goes here
    }
}

protocols as types

由于protocol也是一種類型矾削,所以protocol可以和其他類型一樣用在很多地方壤玫,比如:

  1. 可以作為參數(shù)類型或者function豁护、method、initializer的返回值欲间。

  2. 可以作為一個常量楚里、變量或者property。

  3. 可以作為Array猎贴、dictionary或其他容器類型的內(nèi)容班缎。

例如:

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

可以給generator賦值給任意實(shí)現(xiàn)了RandomNumberGenerator的instance。

protocol還可以用作代理她渴,這點(diǎn)和oc中差不多达址,就不在多說了。

在class趁耗、enum或structure的extension中實(shí)現(xiàn)protocol


protocol TextRepresentable {
    var textualDescription: String { get }
}

extension Dice: TextRepresentable {
    var textualDescription: String {
        return "A \(sides)-sided dice"
    }
}

如果一個class沉唠、enumeration或者structure已經(jīng)實(shí)現(xiàn)了一個protocol的所有功能,只是沒有顯示的實(shí)現(xiàn)這個protocol对粪,這時可以用一個empty extension來使其adopt這個protocol右冻。

struct Hamster {
    var name: String
    var textualDescription: String {
        return "A hamster named \(name)"
    }
}
extension Hamster: TextRepresentable {}

protocol type的collection

上面說過protocol也是一種類型而且可以存儲在collection中,所以可以創(chuàng)建protocol類型的collection著拭。

let things: [TextRepresentable] = [game, d12, simonTheHamster]

protocol inheritance

protocol可以被繼承纱扭,而且可以多繼承。

protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
    // protocol definition goes here
}

class-only protocols

添加class關(guān)鍵字到protocol繼承列表的最前面儡遮,可以限制protocol只被class實(shí)現(xiàn)乳蛾,而不被enumeration和structure實(shí)現(xiàn)。如下:

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
    // class-only protocol definition goes here
}

protocol composition

可以設(shè)定一個type同時遵守多個protocol鄙币,通過&符號將他們連接起來肃叶,例如:

protocol Named {
    var name: String { get }
}
protocol Aged {
    var age: Int { get }
}
struct Person: Named, Aged {
    var name: String
    var age: Int
}
func wishHappyBirthday(to celebrator: Named & Aged) {
    print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}
let birthdayPerson = Person(name: "Malcolm", age: 21)
wishHappyBirthday(to: birthdayPerson)
// Prints "Happy birthday, Malcolm, you're 21!"

protocol composition并沒有創(chuàng)建一個新的、永久性的protocol十嘿,而只是定義了一個臨時性的protocol把所有的requirement組合到一個protocol中因惭。

checking for protocol conformance

根據(jù)前面的type cast中的介紹,這里同樣有is绩衷、as蹦魔?、as咳燕!來作類型檢測和轉(zhuǎn)換勿决,用法和之前一致,就不在介紹了招盲。

optional protocol requirements

protocol可以定義為optioal低缩,需要在被定義為optional的內(nèi)容前面加關(guān)鍵字optional,估計應(yīng)該是為了與oc兼容。格式如下:

@objc protocol CounterDataSource {
    @objc optional func increment(forCount count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}

摘錄來自: Apple Inc. “The Swift Programming Language (Swift 3)”曹货。 iBooks. 

可以看到protocol定義前面和每個optional的method前面都用@objc修飾咆繁。

protocol extension

可以為protocol本身定義extension讳推。格式為:

extension RandomNumberGenerator {
    func randomBool() -> Bool {
        return random() > 0.5
    }
}

通過extension,我們可以為protocol中的computed property和method定義默認(rèn)的實(shí)現(xiàn)么介,如果實(shí)現(xiàn)這個protocol的Type本身提供了自己的實(shí)現(xiàn)娜遵,則會覆蓋默認(rèn)的實(shí)現(xiàn)蜕衡。

extension PrettyTextRepresentable  {
    var prettyTextualDescription: String {
        return textualDescription
    }
}

我們還可以給protocol的extension添加條件約束壤短,只有符合條件的conforming type才可以使用extension。例如:

extension Collection where Iterator.Element: TextRepresentable {
    var textualDescription: String {
        let itemsAsText = self.map { $0.textualDescription }
        return "[" + itemsAsText.joined(separator: ", ") + "]"
    }
}

使用如下:

let murrayTheHamster = Hamster(name: "Murray")
let morganTheHamster = Hamster(name: "Morgan")
let mauriceTheHamster = Hamster(name: "Maurice")
let hamsters = [murrayTheHamster, morganTheHamster, mauriceTheHamster]

//使用
print(hamsters.textualDescription)
// Prints "[A hamster named Murray, A hamster named Morgan, A hamster named Maurice]

如果一個confirming type對同一個method和property符合多個extensions約束慨仿,則swift會自動從這些extension中挑選一個最合適的選線久脯。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市镰吆,隨后出現(xiàn)的幾起案子帘撰,更是在濱河造成了極大的恐慌,老刑警劉巖万皿,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件摧找,死亡現(xiàn)場離奇詭異,居然都是意外死亡牢硅,警方通過查閱死者的電腦和手機(jī)蹬耘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來减余,“玉大人综苔,你說我怎么就攤上這事∥徊恚” “怎么了如筛?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長抒抬。 經(jīng)常有香客問我杨刨,道長,這世上最難降的妖魔是什么擦剑? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任妖胀,我火速辦了婚禮,結(jié)果婚禮上抓于,老公的妹妹穿的比我還像新娘做粤。我一直安慰自己,他們只是感情好捉撮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布怕品。 她就那樣靜靜地躺著,像睡著了一般巾遭。 火紅的嫁衣襯著肌膚如雪肉康。 梳的紋絲不亂的頭發(fā)上闯估,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機(jī)與錄音吼和,去河邊找鬼涨薪。 笑死,一個胖子當(dāng)著我的面吹牛炫乓,可吹牛的內(nèi)容都是我干的刚夺。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼末捣,長吁一口氣:“原來是場噩夢啊……” “哼侠姑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起箩做,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤莽红,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后邦邦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體安吁,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年燃辖,在試婚紗的時候發(fā)現(xiàn)自己被綠了鬼店。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡郭赐,死狀恐怖薪韩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捌锭,我是刑警寧澤俘陷,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站观谦,受9級特大地震影響拉盾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜豁状,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一捉偏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧泻红,春花似錦夭禽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春潮梯,著一層夾襖步出監(jiān)牢的瞬間骗灶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工秉馏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留耙旦,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓萝究,卻偏偏與公主長得像免都,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子糊肤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評論 2 355

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