內容參考2.21協議_第1頁
內容參考2.21協議_第2頁
內容參考2.21協議_第3頁
內容參考2.21協議_第4頁
內容參考2.21協議_第5頁
已閱讀5頁,還剩15頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、翻譯:geek5nan校對:dabing1022協議本頁包含內容:協議的語法(Protocol Syntax)屬性要求(Property Requirements)方法要求(Method Requirements)突變方法要求(Muing Method Requirements)協議類型(Protocols as Types)委托()模式(Delegation)在擴展中添加協議成員(Adding Protocol Conformance wi Exten)n通過延展補充協議Exten)(Declaring Protocol Adoption win集合中的協議類型(Collections of

2、 Protocol Types)協議的繼承(Protocol Inheritance)協議(Protocol Comition)檢驗協議的一致性(Checking for Protocol Conformance)可選協議要求(Optional Protocol Requirements)Protocol(協議)用于統一方法和屬性的名稱,而不實現任何功能。協議能夠被類,枚舉,結構體實現,滿足協議要求的類,枚舉,結構體被稱為協議的。需要提供協議指定的成員,如屬性,方法,操作符,下標等。協議的語法的定義與類,結構體,枚舉的定義非常相似,如下所示:協議遵循者遵循者當某個類含有父類的同時并實現了協議,

3、應當把父類放在所有的協議之前,如下所示:屬性要求通常前置var關鍵字將屬性聲明為變量。在屬性聲明后寫上 get set 表示屬性為可讀寫的。 get 用來表示屬性為可讀的。即使你為可讀的屬性實現了setter方法,它也不會出錯。用類來實現協議時,使用class關鍵字來表示該屬性為類成員;用結構體或枚舉實現協議時,則使用static關鍵字來表示:protocol SomeProtocol var musBeSettable : Int get set var doesNotNeedToBeSettable: Int get 協議能夠要求其遵循者必須含有一些特定名稱和類型的實例屬性(instanc

4、e property)或類屬性 (type property),也能夠要求屬性的(設置權限)settable 和(訪問權限)gettable,但它不要求屬性是存儲型屬性(stored property)還是計算型屬性(calculate property)。class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol / 類的內容struct SomeStructure: FirstProtocol, AnotherProtocol/ 結構體內容protocol SomeProtocol / 協議內容在類,結構體,枚舉的名稱后加

5、上協議名稱,中間以冒號:分隔即可實現協議;實現多個協議時,各協議之間用逗號,分隔,如下所示:protocol AnotherProtocol class var someTypeProperty: Int get set protocol FullyNamed var fullName: String get FullyNamed協議含有fullName屬性。因此其遵循者必須含有一個名為 fullName,類型為String的可讀屬性。struct Person: FullyNamed var fullName: Stringlet john = Person(fullName: John A

6、ppleseed)/john.fullName 為 John AppleseedPerson結構體含有一個名為fullName的存儲型屬性,完整的遵循了協議。(若協議未被完整遵循,編譯時則會報錯)。如下所示,Startship類遵循了FullyNamed協議:class Starship: FullyNamed var prefix: String? var name: Stringinit(name: String, prefix: Stirng? = nil ) self.anme = nameself.prefix = prefixvar fullName: String return

7、(prefix ? prefix ! + : ) + namevar ncc1701 = Starship(name: Enterprise, prefix:USS)/ ncc1701.fullName = USS EnterpriseStarship類將fullName實現為可讀的計算型屬性。它的每一個實例都有一個名為name的必備屬性和一個名為prefix的可選屬性。 當prefix存在時,將prefix插入到name之前來為Starship構建fullName。方法要求能夠要求其必備某些特定的實例方法和類方法。協議方法的與普通方法注意:相似,但它不需要內容。協議方法支持變長參數(vari

8、adic parameter),不支持默認參數(default parameter)。前置class關鍵字表示協議中的成員為類成員;當協議用于被枚舉或結構 遵循時,則使用sic關鍵字。如下所示:protocol SomeProtocol class func someTypeMethod()protocol RandomNumberGenerator func random() - DoubleRandomNumberGenerator協議要求其遵循者必須擁有一個名為random,返回值類型為Double的實例方法。(假設隨機數在0,1區(qū)間內)。LinearCongruentialGenera

9、tor類遵循了RandomNumberGenerator協議,并提供了一個叫做線性同余生成器(linear congruential generator)的偽隨機數算法。class LinearCongruentialGenerator: RandomNumberGenerator var lastRandom = 42.0 let m = 139968.0let a = 3877.0 let c = 29573.0func random() - Double 體方法遵循者協議突變方法要求能在或函數改變實例類型的方法稱為突變方法。在值類型(Value Type)(譯者注:特指結構體和枚舉)中的

10、的函數前綴加上muing關鍵字來表示該函數允許改變該實例和其屬性的類型。 這一變換過程在實例方法(Instance Methods)章節(jié)中有詳細描述。(譯者注:類中的成員為引用類型(Reference Type),可以方便的修改實例及其屬性的值而無需改變類型;而結構體和中的成員均為值類型(Value Type),修改變量的值就相當于修改變量的類型,而Swift默認不允許修改類型,因此需要前置muing關鍵字用來表示該函數中能夠修改類型)注意:用class實現協議中的muing方法時,不用寫muing關鍵字;用,實現協議中的muing方法時,必須寫muing關鍵字。如下所示,Togglable協

11、議含有toggle函數。根據函數名稱推測,用于切換或恢復某個屬性的狀態(tài)。muing關鍵字表示它為:protocol Togglable muing func toggle()當使用枚舉或結構體來實現Togglabl協議時,必須在toggle方法前加上toggle可能突變方法枚舉構體結枚舉方法lastRandom = (lastRandom * a + c) % m) return lastRandom / mlet generator = LinearCongruentialGenerator() prln(Heres a random number: (generator.random()/

12、 輸出 : Heres a random number: 0.37464991998171prln(And another one: (generator.random()/ 輸出 : And another one: 0.729023776863283muing關鍵字。如下所示,OnOffSwitch枚舉遵循了Togglable協議,On,Off兩個成員用于表示當前狀態(tài)協議類型本身不實現任何功能,但你可以將它當做來使用。使用場景:作為函數,方法或構造器中的參數類型,返回值類型作為常量,變量,屬性的類型作為數組,字典或其他容器中的元素類型注意:協議類型應與其他類型(,Double,String

13、)的寫法相同,使用駝峰式class Dice let sides:let generator: init(sides:RandomNumberGenerator, generator:類型協議enum OnOffSwitch: Togglable case Off, Onmuing func toggle() switch self case Off:self = On case On:self = Offvar lightSwitch = OnOffSwitch.Off lightSwitch.toggle()/lightSwitch 現在的值為 .OnDice含有sides和generat

14、or兩個屬性,前者用來表示骰子有幾個面,后者為骰子提供一個隨機數生成器。由于后者為RandomNumberGenerator的協議類型。所以它能夠被賦值為任意該協議的類型。此外,使用構造器(init)來代替之前版本中的setup操作。構造器中含有一個名為generator,類型為RandomNumberGenerator的形參,使得它可以接收任意遵循RandomNumberGenerator協議的類型。roll方法用來模擬骰子的面值。它先使用generator的random方法來創(chuàng)建一個0-1區(qū)間內的隨機數種子,然后加工這個隨機數種子生成骰子的面值。如下所示,LinearCongruentia

15、lGenerator的實例作為隨機數生成器傳入Dice的構造器var d6 = Diides: 6,generator: LinearCongruentialGenerator() for _ in 1.5 prln(Random dice roll is (d6.roll()/輸出結果/Random dice roll is 3/Random dice roll is 5/Random dice roll is 4/Random dice roll is 5/Random dice roll is 4遵循RandomNumberGenerator) self.sides = sides se

16、lf.generator = generatorfunc roll() -return(generator.random() * Double(sides) +1這里定義了一個名為 Dice的類,用來代表桌游中的N個面的骰子。委托()模式委托是一種設計模式,它允許類或結構體將一些需要它們負責的功能(委托)給其他的類型。委托模式的實現很簡單: 定義協議來封裝那些需要被委托的函數和方法,使其遵循者擁有這些被委托的。委托模式可以用來響應特定的動作或接收外部數據源提供的數據,而無需要知道外部數據源的類型。下文是兩個基于骰子的協議:如下所示,SnakesAndLadders是Snakes and Lad

17、ders(譯者注:控制流章節(jié)有該的詳細介紹)的新版本。新版本使用Dice作為骰子,并且實現了DiceGame和DiceGameDelegate協議clasakesAndLadders: DiceGame let finalSquare = 25let dic = Diides: 6, generator: LinearCongruentialGenerator()var square = 0protocol DiceGame var dice: Dice get func play()protocol DiceGameDelegate func gameDidStart(game: DiceG

18、ame) func game(game: DiceGame,didStartNewTurnWithDiceRoll diceRoll:) func gameDidEnd(game: DiceGame)DiceGame協議可以在任意含有骰子的中實現,DiceGameDelegate協議可以用來追蹤DiceGame的過程。函數和方法交由注意:var board: init() board =(count: finalSquare + 1, repeatedValue: 0)board03 = +08; board06 = +11; borad09 =+09; board10 = +02borad1

19、4 = -10; board19 = -11; borad22 =-02; board24 = -08var delegate: DiceGameDelegate? func play() square = 0 delegate?.gameDidStart(self)gameLoop: while square != finalSquare let diceRoll = dice.roll()delegate?.game(self,didStartNewTurnWithDiceRoll: diceRoll)switch square + diceRoll case finalSquare:br

20、eak gameLoopcase let newSquare where newSquare finalSquare:continue gameLoop default:square += diceRoll square += boardsquaredelegate?.gameDIdEnd(self)的初始化設置(setup)被SnakesAndLadders類的構造器(initializer)實現。所有的邏輯被轉移到了play方法中。因為delegate并不是該的必備條件,delegate被定義為遵循DiceGameDelegate協議的可選屬性DicegameDelegate協議提供了三個

21、方法用來追蹤過程。被放置于游戲的邏輯中,即play()方法內。分別在戲結束時被調用。開始時,新一輪開始時,游因為delegate是一個遵循DiceGameDelegate的可選屬性,因此在 play()方法中使用了可選鏈來調用委托方法。 若delegate屬性為nil,則委托調用優(yōu)雅地失效。若delegate不為nil,則委托方法被調用如下所示,DiceGameTracker遵循了DiceGameDelegate協議class DiceGameTracker: DiceGameDelegate var numberOfTurns = 0func gameDidStart(game: DiceG

22、ame) numberOfTurns = 0ifgame i prakesAndLadders ln(Started a new gameoakesandLadders)pr(game.diln(The game is using a ides)-sided dice)func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll:+numberOfTurns)prln(Rolled a(diceRoll)func gameDidEnd(game:DiceGame) lasted for (numberOfTurns)prln(Th

23、e gameturns)DiceGameTracker實現了DiceGameDelegate協議的方法要求,用來記錄已經進行的輪數。 當開始時,numberOfTurns屬性被賦值為0;在每新一輪中遞加;結束后,輸出打印的總輪數。gameDidStart方法從game參數獲取信息并輸出。game在方法中被當做DiceGame類型而不是SnakeAndLadders類型,所以方法中只能DiceGame協議中的成員。DiceGameTracker的運行情況,如下所示:在擴展中添加協議成員即便無法修改源代碼,依然可以通過擴展(Exion)來擴充已存在類型(譯者注: 類,結構體,枚舉等)。擴展可以為已

24、存在的類型添加屬性,法,協議等成員。在擴展章節(jié)中查看。注意:通過為已存在的類型遵循協議時,該類型的所有實例也會隨之添加協議中的方法TextRepresentable協議含有一個asText,如下所示:protocol TextRepresentable func asText() - String通過擴展為上一節(jié)中提到的Dice類遵循TextRepresentable協議extenDice: TextRepresentable 擴展下標方“l(fā)et tracker = DiceGameTracker() let game = SnakesAndLadders() game.delegate =

25、tracker game.play()/ Started a new game oakes and Ladders/ The game is using a 6-sided dice/ Rolled a 3/ Rolled a 5/ Rolled a 4/ Rolled a 5/ The game lasted for 4 turns”從現在起,Dice類型的實例可被當作TextRepresentable類型:let d12 = Diides: 12,generator:LinearCongruentialGenerator()prln(d12.asText()輸出 A 12-sided di

26、ce/SnakesAndLadders類也可以通過擴展的方式來遵循協議:通過延展補充協議當一個類型已經實現了協議中的所有要求,卻沒有時,可以通過來補充協議:strucmster var name: Stringfunc asText() - String return A hamster named (name)extenHamster: TextRepresentabl 從現在起,Hamster的實例可以作為TextRepresentable類型使用let simonTheHamster = Hamster(name: Simon)擴展extenSnakeAndLadders: TextRe

27、presentable func asText() - String return A game oakes and Ladders with (finalSquare) squaresprln(game.asText()/ 輸出 A gamSnakes and Ladders with 25 squarescun asText() - String return A (sides)-sided dice注意:即時滿足了協議的所有要求,類型也不會自動轉變,因此你必須為它做出明顯的協議集合中的協議類型協議類型可以被集合使用,表示集合中的元素均為協議類型:如下所示,things數組可以被直接遍歷,

28、并調用其中元素的asText()函數:for thing prhings ln(thing.asText()/A A Agame oakes and Ladders with 25 squares12-sided dice hamster named Simonthing被當做是TextRepresentable類型而不是Dice,DiceGame, Hamster等類型。因此能且僅能調用asText方法協議的繼承協議能夠繼承一到多個其他協議。語法與類的繼承相似,多個協議間用逗號,分隔protocol InheritingProtocol: SomeProtocol,Anothrotocol

29、let things: TextRepresentable =game,d12,simoTheHamsterlet somethingTextRepresentable: TextRepresentabl = simonTheHamesterprln(somethingTextRepresentable.asText()/ 輸出 A hamster named Simon如下所示,PrettyTextRepresentable協議繼承了TextRepresentable協議遵循PrettyTextRepresentable協議的同時,也需要遵循TextRepresentable協議。如下所示,

30、用為SnakesAndLadders遵循PrettyTextRepresentable協議:當從數組中迭代出的元素的值大于0時,用表示當從數組中迭代出的元素的值小于0時,用表示當從數組中迭代出的元素的值等于0時,用表示任意SesAndLadders的實例都可以使用asPrettyText()方法。prln(game.asPrettyText()extenSnakesAndLadders: PrettyTextRepresentable func asPrettyText() - String var output = asText() + :n for index in 1.finalSqua

31、re switch boardindex case let ladder where ladder 0: output += case let snake where snake String/ 協議定義協議合成一個協議可由多個協議采用protocol這樣的格式進行組合,稱為協議合成(protocol composition)。舉個例子:wishHappyBirthday函數的形參celebrator的類型為 protocol。可以傳入任意遵循這兩個協議的類型的實例protocol Named var name: String get protocol Aged var age: Int ge

32、t struct Person: Named, Aged var name: Stringvar age: Intfunc wishHappyBirthday(celebrator: protocol) println(Happy birthday () - youre (celebrator.age)!)let birthdayPerson = Person(name: Malcolm, age: 21) wishHappyBirthday(birthdayPerson)/ 輸出 Happy birthday Malcolm - youre 21!Named協議包含String類型的name

33、屬性;Aged協議包含Int類型的age屬性。Person結構體遵循了這兩個協議。/ A game of Snakes and Ladders with 25 squares:/ 注意:并不會生成一個新協議類型,而是將多個協議合成為一個臨時的協議,超出范圍后立即失效。檢驗協議的一致性使用is檢驗協議一致性,使用as將協議類型向下轉換(downcast)為的其他協議類型。檢驗與轉換的語法和之前相同(詳情查看類型檢查):is操作符用來檢查實例是否遵循了某個協議。as?返回一個可選值,當實例遵循協議時,返回該協議類型;否則返回nilas用以強制向下轉換型。objc protocol HasArea

34、var area: Double get 注意:objc用來表示協議是可選的,也可以用來表示暴露給Objective-C的代碼,此外,objc型協議只對類有效,因此只能在類中檢查協議的一致性。詳情查看Using Siwft with Cocoa and Objectivei-c。class Circle: HasArea let var varpi = 3.1415927radius: Double area:radius init(radius: Double) self.radius = radius class Country: HasArea var area: Doubleinit(

35、area: Double) self.area = area Circle和Country都遵循了HasArea協議,前者把area寫為計算型屬性(computed property),后者則把area寫為存儲型屬性(storedproperty)。協議合成如下所示,Animal類沒有實現任何協議Circle,Country,Animal并沒有一個相同的基類,所以采用AnyObject類型的數組來裝載在他們的實例,如下所示:objects數組中元素的類型并不會因為向下轉型而改變,當它們被賦值給 objectWithArea時只被視為HasArea類型,因此只有area屬性能夠被訪問。for o

36、bject in objects if let objectWithArea = object as? HasArea println(Area is (objectWithArea.area) else println(Something that doesnt have anarea)/ Area is 12.5663708/ Area is 243610.0/ Something that doesnt have an area當數組中的元素遵循HasArea協議時,通過as?操作符將其可選綁定(optional binding)到objectWithArea常量上。let object

37、s: AnyObject = Circle(radius: 2.0), Country(area: 243_610), Animal(legs: 4)如下所示,在迭代時檢查object數組的元素是否遵循了HasArea協議:class Animal var legs: Intinit(legs: Int) self.legs = legs 可選協議要求可選協議含有可選成員,其可以選擇是否實現這些成員。在協議中使用optional關鍵字作為前綴來定義可選成員??蛇x協議在調用時使用可選鏈,詳細內容在可選鏈章節(jié)中查看。像someOptionalMethod?(someArgument)一樣,你可以在

38、可選方法名稱后加上?來檢查該方法是否被實現。可選方法和可選屬性都會返回一個選值(optional value),當其不可回nil。注意:時,?之后語句不會執(zhí)行,并返可選協議只能在含有objc前綴的協議中生效。且objc的協議只能被類遵循。Counter類使用CounterDataSource類型的外部數據源來提供增量值(increment amount),如下所示:objc protocol CounterDataSource optional func incrementForCount(count:) -optional var fixedIncrement: get CounterDataSource含有incrementForCount的可選方法和 fiexdIncrement的可選屬性。注意:Co

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論