Swift 學習筆記(面向協議編程)

來源:互聯網
上載者:User

標籤:計算   com   string   系統   nbsp   ini   觀察   guard   特性   

在Swift中協議不僅可以定義方法和屬性,而且協議是可以擴充的,最關鍵的是,在協議的擴充中可以添加一些方法的預設實現,就是在協議的方法中可以實現一些邏輯,由於這個特性,Swift是可以面向協議進行編程的。

擴充協議和預設實現
protocol Record {    var wins: Int{get}    var losses:Int{get}    func winningPercent() -> Double}struct BasketballRecord:Record,CustomStringConvertible {    var wins: Int    var losses: Int        func winningPercent() -> Double {        return Double(wins)/Double(wins + losses)    }    var description: String {        return String.init(format: "WINS: %d, LOSSES: %d", [wins,losses])    }}struct baseballRecord:Record,CustomStringConvertible {    var wins: Int    var losses: Int        func winningPercent() -> Double {        return Double(wins)/Double(wins + losses)    }    var description: String {        return String.init(format: "WINS: %d, LOSSES: %d", [wins,losses])    }}let teamRecord = BasketballRecord(wins: 2, losses: 10)print(teamRecord)let baseball = baseballRecord(wins: 3, losses: 10)print(baseball)

我們可以看到 這兩個結構體 都分別繼承了Record 和 CustomStringConvertible協議 其中第一個是我們自訂的協議 第二個是系統協議,在Swift中協議也是可以繼承的,於是我們可以改寫成下面的模式。

protocol Record:CustomStringConvertible {    var wins: Int{get}    var losses:Int{get}    func winningPercent() -> Double}struct BasketballRecord:Record {    var wins: Int    var losses: Int        func winningPercent() -> Double {        return Double(wins)/Double(wins + losses)    }    var description: String {        return String.init(format: "WINS: %d, LOSSES: %d", [wins,losses])    }}struct baseballRecord:Record {    var wins: Int    var losses: Int        func winningPercent() -> Double {        return Double(wins)/Double(wins + losses)    }    var description: String {        return String.init(format: "WINS: %d, LOSSES: %d", [wins,losses])    }}

你會看到還是有冗餘的代碼 就是遵守CustomStringConvertible協議 實現的description的返回時一樣的,這個時候我們就像進一步封裝,那麼我們該怎麼做呢?這個其實就用到我們所說:協議是可以擴充的,而且在擴充中協議的屬性和方法是可以有預設實現的,我們可以這樣寫:

protocol Record:CustomStringConvertible {    var wins: Int{get}    var losses:Int{get}    func winningPercent() -> Double}//擴充協議extension Record {        var description: String {        return String.init(format: "WINS: %d, LOSSES: %d", [wins,losses])    }}struct BasketballRecord:Record {    var wins: Int    var losses: Int        func winningPercent() -> Double {        return Double(wins)/Double(wins + losses)    }    }struct baseballRecord:Record {    var wins: Int    var losses: Int        func winningPercent() -> Double {        return Double(wins)/Double(wins + losses)    }}

這樣寫是不是就方便多了呢,但是仔細觀察 我們在遵守協議的各個結構體中是不是還有邏輯類似,但是寫了好幾遍的代碼呢,我們是不是也可以考慮,將計算勝率的方法也遷移到擴充中呢?

protocol Record:CustomStringConvertible {    var wins: Int {get}    var losses:Int {get}    }//擴充協議extension Record {        var description: String {        return String.init(format: "wins: %d, losses:%d", [wins,losses])    }        var gamePlayed:Int {        return wins + losses    }        func winningPercent() -> Double {        return Double(wins)/Double(gamePlayed)    }    }struct BasketballRecord:Record {    var wins: Int    var losses: Int}struct baseballRecord:Record {    var wins: Int    var losses: Int}

是不是更加簡便了呢,那麼假如一場比賽既有輸贏,又有打平的時候呢,我們新增加一個協議,當遵守了不同的協議,他們執行的預設方法,就是既滿足了有輸贏又可以打平裡面擴充的方法的預設實現,如果只遵守了一個Record協議,則執行擴充Record中的預設實現。

protocol Record:CustomStringConvertible {    var wins: Int {get}    var losses:Int {get}    }//打平的協議protocol Tieable {    var ties:Int {get set}}//擴充即遵守了Record協議的又遵守了Tieable協議extension Record where Self:Tieable {    var gamePlayed:Int {        return wins + losses + ties    }    func winningPercent() -> Double {        return Double(wins)/Double(gamePlayed)    }}//擴充協議extension Record {        var description: String {        return String.init(format: "wins: %d, losses:%d", [wins,losses])    }        var gamePlayed:Int {        return wins + losses    }        func winningPercent() -> Double {        return Double(wins)/Double(gamePlayed)    }    }struct BasketballRecord:Record {    var wins: Int    var losses: Int}struct baseballRecord:Record {    var wins: Int    var losses: Int}//可以平局的struct FootBallRecord:Record,Tieable {    var wins: Int    var losses: Int    var ties: Int}
協議彙總

文法結構

協議1 & 協議2

範例程式碼

//判斷是否可以獲得獎勵的協議protocol Prizable {    func isPrizable() -> Bool}func award(prizable: Prizable & CustomStringConvertible){    if prizable.isPrizable() {        print(prizable)        print("你可以獲獎")    }else{        print("您不可以獲獎")    }}

表示這個函數的參數 即遵守Prizable協議,也遵守了CustomStringConvertible的協議。

泛型約束
struct Student:CustomStringConvertible,Equatable,Comparable,Prizable{    var name:String    var score:Int    var description: String {        return name    }    func isPrizable() -> Bool {        return score > 60    }}func == (s1:Student,s2:Student)->Bool {    return s1.score == s2.score}func < (s1:Student,s2:Student) ->Bool {    return s1.score < s2.score}let tian = Student(name: "tian", score: 90)let a = Student(name: "Alice", score: 80)let b = Student(name: "Bob", score: 67)let c = Student(name: "Karl", score: 66)let students = [a,b,c,tian]//報錯 原因是因為Comparable 這個協議的實現中自己調用了自己 此時這種協議不能當作一種類型 在這種情況下我們可以改為下面的代碼func topOne(seq:[Comparable]) ->Comparable {     }

為瞭解決上面的錯誤,我們可以這樣寫

struct Student:CustomStringConvertible,Equatable,Comparable,Prizable{    var name:String    var score:Int    var description: String {        return name    }    func isPrizable() -> Bool {        return score > 60    }}func == (s1:Student,s2:Student)->Bool {    return s1.score == s2.score}func < (s1:Student,s2:Student) ->Bool {    return s1.score < s2.score}let tian = Student(name: "tian", score: 90)let a = Student(name: "Alice", score: 80)let b = Student(name: "Bob", score: 67)let c = Student(name: "Karl", score: 66)let students = [a,b,c,tian]func topOne<T:Comparable>(seq:[T]) ->T  {    assert(seq.count > 0)    return seq.reduce(seq[0]){        max($0, $1)    }}topOne(seq: [4,5,7,8])func topPrizableOne<T:Comparable & Prizable>(seq:[T]) ->T? {    return seq.reduce(nil) {        (tempTop:T?,contender:T) in        guard contender.isPrizable() else {            return tempTop        }        guard let tempTop = tempTop else {            return contender        }                return max(tempTop, contender)    }}topPrizableOne(seq: students)?.name

 

Swift 學習筆記(面向協議編程)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.