日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

swift学习笔记之-协议

發(fā)布時(shí)間:2025/3/15 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 swift学习笔记之-协议 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

//協(xié)議(Protocols)

?

import UIKit

?

/*協(xié)議(Protocols)

? ? 1.協(xié)議定義了一個(gè)藍(lán)圖,規(guī)定了用來實(shí)現(xiàn)某一特定任務(wù)或者功能的方法、屬性,以及其他需要的東西

? ? 2.類、結(jié)構(gòu)體或枚舉都可以采納協(xié)議,并為協(xié)議定義的這些要求提供具體實(shí)現(xiàn)。某個(gè)類型能夠滿足某個(gè)協(xié)議的要求,就可以說該類型“符合”這個(gè)協(xié)議。

? ? 3.除了采納協(xié)議的類型必須實(shí)現(xiàn)的要求外,還可以對(duì)協(xié)議進(jìn)行擴(kuò)展,通過擴(kuò)展來實(shí)現(xiàn)一部分要求或者實(shí)現(xiàn)一些附加功能,這樣采納協(xié)議的類型就能夠使用這些功能。

協(xié)議定義語法:? protocol SomeProtocol { // 這里是協(xié)議的定義部分 }

協(xié)議的采納:擁有父類的類在采納協(xié)議時(shí),應(yīng)該將父類名放在協(xié)議名之前,以逗號(hào)分隔:

? ? ? ? class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {

? ? ? ? ? ? // 這里是類的定義部分

? ? ? ? }

?

屬性要求:

? ? 1.協(xié)議可以要求采納協(xié)議的類型提供特定名稱和類型的實(shí)例屬性或類型屬性。協(xié)議不指定屬性是存儲(chǔ)型屬性還是計(jì)算型屬性,它只指定屬性的名稱和類型。

? ? 2.協(xié)議還指定屬性是只讀的還是可讀可寫的

? ? 3.如果協(xié)議要求屬性是可讀可寫的,那么該屬性不能是常量屬性或只讀的計(jì)算型屬性。如果協(xié)議只要求屬性是只讀的,那么該屬性不僅可以是只讀的,如果代碼需要的話,還可以是可寫的

protocol SomeProtocol {

? ? var mustBeSettable: Int { get set } ? ? //表示屬性是可讀可寫的

? ? static var doesNotNeedToBeSettable: Int { get }? ? ? ? //類型屬性、只讀屬性,static 關(guān)鍵字,類類型的還可以使用 class 關(guān)鍵字來聲明類型屬性

}

?

方法要求:

? ? 1.協(xié)議可以要求采納協(xié)議的類型實(shí)現(xiàn)某些指定的實(shí)例方法或類型方法。這些方法作為協(xié)議的一部分,像普通方法一樣放在協(xié)議的定義中,但是不需要大括號(hào)和方法體??梢栽趨f(xié)議中定義具有可變參數(shù)的方法,和普通方法的定義方式相同。但是,不支持為協(xié)議中的方法的參數(shù)提供默認(rèn)值。

? ? 2.在協(xié)議中定義類型方法的時(shí)候,總是使用 static 關(guān)鍵字作為前綴。當(dāng)類類型采納協(xié)議時(shí),除了 static 關(guān)鍵字,還可以使用 class 關(guān)鍵字作為前綴

? ? 3.值類型的Mutating 方法要求:若需要在值類型的方法中修改方法所屬的實(shí)例,將 mutating 關(guān)鍵字作為方法的前綴

?

構(gòu)造器要求:協(xié)議可以要求采納協(xié)議的類型實(shí)現(xiàn)指定的構(gòu)造器

? ? 1.你可以在采納協(xié)議的類中實(shí)現(xiàn)構(gòu)造器,無論是作為指定構(gòu)造器,還是作為便利構(gòu)造器。無論哪種情況,你都必須為類的構(gòu)造器實(shí)現(xiàn)標(biāo)上 required 修飾符:

? ? 2.使用 required 修飾符可以確保所有子類也必須提供此構(gòu)造器實(shí)現(xiàn),從而也能符合協(xié)議

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

?

協(xié)議作為類型:

? ? 1.盡管協(xié)議本身并未實(shí)現(xiàn)任何功能,但是協(xié)議可以被當(dāng)做一個(gè)成熟的類型來使用。

? ? 2.協(xié)議可以像其他普通類型一樣使用,使用場景如下:

? ? ? ? 1.作為函數(shù)、方法或構(gòu)造器中的參數(shù)類型或返回值類型

? ? ? ? 2.作為常量、變量或?qū)傩缘念愋?/p>

? ? ? ? 3.作為數(shù)組、字典或其他容器中的元素類型

委托(代理)模式:嵌套

? ? 1.委托是一種設(shè)計(jì)模式,它允許類或結(jié)構(gòu)體將一些需要它們負(fù)責(zé)的功能委托給其他類型的實(shí)例。

? ? 2.委托模式的實(shí)現(xiàn)很簡單:定義協(xié)議來封裝那些需要被委托的功能,這樣就能確保采納協(xié)議的類型能提供這些功能。

? ? 3.委托模式可以用來響應(yīng)特定的動(dòng)作,或者接收外部數(shù)據(jù)源提供的數(shù)據(jù),而無需關(guān)心外部數(shù)據(jù)源的類型

通過擴(kuò)展采納協(xié)議:

? ? 1.即便無法修改源代碼,依然可以通過擴(kuò)展令已有類型采納并符合協(xié)議。擴(kuò)展可以為已有類型添加屬性、方法、下標(biāo)腳本以及構(gòu)造器,因此可以符合協(xié)議中的相應(yīng)要求。通過擴(kuò)展令已有類型采納并符合協(xié)議時(shí),該類型的所有實(shí)例也會(huì)隨之獲得協(xié)議中定義的各項(xiàng)功能。

? ? 2.當(dāng)一個(gè)類型已經(jīng)符合了某個(gè)協(xié)議中的所有要求,卻還沒有聲明采納該協(xié)議時(shí),可以通過空擴(kuò)展體的擴(kuò)展來采納該協(xié)議

協(xié)議類型的集合:協(xié)議類型可以在數(shù)組或者字典這樣的集合中使用,所有采納某協(xié)議的類型實(shí)例,雖然類型各不相同,但都是該協(xié)議類型

?

協(xié)議的繼承:協(xié)議能夠繼承一個(gè)或多個(gè)其他協(xié)議,可以在繼承的協(xié)議的基礎(chǔ)上增加新的要求。協(xié)議的繼承語法與類的繼承相似,多個(gè)被繼承的協(xié)議間用逗號(hào)分隔:

? ? protocol InheritingProtocol: SomeProtocol, AnotherProtocol {

? ? ? ? // 這里是協(xié)議的定義部分

? ? }

類類型專屬協(xié)議:在協(xié)議的繼承列表中,通過添加 class 關(guān)鍵字來限制協(xié)議只能被類類型采納,如果嘗試讓結(jié)構(gòu)體或枚舉類型采納該協(xié)議,則會(huì)導(dǎo)致編譯錯(cuò)誤。

? ? ? ? protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {

? ? ? ? ? ? // 這里是類類型專屬協(xié)議的定義部分

? ? ? ? }

?

協(xié)議合成:有時(shí)候需要同時(shí)采納多個(gè)協(xié)議,你可以將多個(gè)協(xié)議采用 protocol<SomeProtocol, AnotherProtocol> 這樣的格式進(jìn)行組合,稱為 協(xié)議合成(protocol composition)。你可以在 <> 中羅列任意多個(gè)你想要采納的協(xié)議,以逗號(hào)分隔

?

檢查協(xié)議一致性:

? ? 1.你可以使用類型轉(zhuǎn)換中描述的 is 和 as 操作符來檢查協(xié)議一致性,即是否符合某協(xié)議,并且可以轉(zhuǎn)換到指定的協(xié)議類型。

? ? 2.檢查和轉(zhuǎn)換到某個(gè)協(xié)議類型在語法上和類型的檢查和轉(zhuǎn)換完全相同:

? ? ? ? is 用來檢查實(shí)例是否符合某個(gè)協(xié)議,若符合則返回 true,否則返回 false。

? ? ? ? as? 返回一個(gè)可選值,當(dāng)實(shí)例符合某個(gè)協(xié)議時(shí),返回類型為協(xié)議類型的可選值,否則返回 nil。

? ? ? ? as! 將實(shí)例強(qiáng)制向下轉(zhuǎn)換到某個(gè)協(xié)議類型,如果強(qiáng)轉(zhuǎn)失敗,會(huì)引發(fā)運(yùn)行時(shí)錯(cuò)誤。

?

可選的協(xié)議要求:

? ? 1.協(xié)議可以定義可選要求,采納協(xié)議的類型可以選擇是否實(shí)現(xiàn)這些要求。

? ? 2.在協(xié)議中使用 optional 關(guān)鍵字作為前綴來定義可選要求。

? ? 3.使用可選要求時(shí)(例如,可選的方法或者屬性),它們的類型會(huì)自動(dòng)變成可選的

? ? 4.協(xié)議中的可選要求可通過可選鏈?zhǔn)秸{(diào)用來使用,因?yàn)椴杉{協(xié)議的類型可能沒有實(shí)現(xiàn)這些可選要求

? ? 5.可選的協(xié)議要求只能用在標(biāo)記 @objc 特性的協(xié)議中。該特性表示協(xié)議將暴露給 Objective-C 代碼,詳情參見Using Swift with Cocoa and Objective-C(Swift 2.1)。即使你不打算和 Objective-C 有什么交互,如果你想要指定可選的協(xié)議要求,那么還是要為協(xié)議加上 @obj 特性。還需要注意的是,標(biāo)記 @objc 特性的協(xié)議只能被繼承自 Objective-C 類的類或者 @objc 類采納,其他類以及結(jié)構(gòu)體和枚舉均不能采納這種協(xié)議。

?

協(xié)議擴(kuò)展:

? ? 1.協(xié)議可以通過擴(kuò)展來為采納協(xié)議的類型提供屬性、方法以及下標(biāo)腳本的實(shí)現(xiàn)。通過這種方式,你可以基于協(xié)議本身來實(shí)現(xiàn)這些功能,而無需在每個(gè)采納協(xié)議的類型中都重復(fù)同樣的實(shí)現(xiàn),也無需使用全局函數(shù)

? ? 2.提供默認(rèn)實(shí)現(xiàn):可以通過協(xié)議擴(kuò)展來為協(xié)議要求的屬性、方法以及下標(biāo)腳本提供默認(rèn)的實(shí)現(xiàn)。如果采納協(xié)議的類型為這些要求提供了自己的實(shí)現(xiàn),那么這些自定義實(shí)現(xiàn)將會(huì)替代擴(kuò)展中的默認(rèn)實(shí)現(xiàn)被使用。

? ? 3.為協(xié)議擴(kuò)展添加限制條件:在擴(kuò)展協(xié)議的時(shí)候,可以指定一些限制條件,只有采納協(xié)議的類型滿足這些限制條件時(shí),才能獲得協(xié)議擴(kuò)展提供的默認(rèn)實(shí)現(xiàn)。這些限制條件寫在協(xié)議名之后,使用 where 子句來描述

*/

protocol FullyNamed {

? ? var fullName: String { get }

}

struct Person: FullyNamed {

? ? var fullName: String

}

let john = Person(fullName: "John Appleseed") ? // john.fullName 為 "John Appleseed"

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") ? // ncc1701.fullName 是 "USS Enterprise"

//========================

protocol RandomNumberGenerator {

? ? func random() -> Double

}

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) % m)

? ? ? ? return lastRandom / m

? ? }

}

let generator = LinearCongruentialGenerator()

print("And another one: \(generator.random())") //每執(zhí)行一次,lastRandom的值就被改變一次

print("And another one: \(generator.random())")

//=====================

class Dice {

? ? let sides: Int

? ? let generator: RandomNumberGenerator? ? //協(xié)議類型

? ? init(sides: Int, generator: RandomNumberGenerator) {

? ? ? ? self.sides = sides

? ? ? ? self.generator = generator

? ? }

? ? func roll() -> Int {

? ? ? ? return Int(generator.random() * Double(sides)) + 1

? ? }

}

var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())

for _ in 1...5 {

? ? print("Random dice roll is \(d6.roll())")

}

//=======================

protocol DiceGame {

? ? var dice: Dice { get }

? ? func play()

}

protocol DiceGameDelegate {

? ? func gameDidStart(game: DiceGame) ? //代理協(xié)議

? ? func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll:Int)

? ? func gameDidEnd(game: DiceGame)

}

class SnakesAndLadders: DiceGame {

? ? let finalSquare = 25

? ? let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())

? ? var square = 0

? ? var board: [Int]

? ? init() {

? ? ? ? board = [Int](count: finalSquare + 1, repeatedValue: 0)

? ? ? ? board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02

? ? ? ? board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08

? ? }

? ? var 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:

? ? ? ? ? ? ? ? break gameLoop

? ? ? ? ? ? case let newSquare where newSquare > finalSquare:

? ? ? ? ? ? ? ? continue gameLoop

? ? ? ? ? ? default:

? ? ? ? ? ? ? ? square += diceRoll

? ? ? ? ? ? ? ? square += board[square]

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? delegate?.gameDidEnd(self)

? ? }

}

class DiceGameTracker: DiceGameDelegate {

? ? var numberOfTurns = 0

? ? func gameDidStart(game: DiceGame) {

? ? ? ? numberOfTurns = 0

? ? ? ? if game is SnakesAndLadders {

? ? ? ? ? ? print("Started a new game of Snakes and Ladders")

? ? ? ? }

? ? ? ? print("The game is using a \(game.dice.sides)-sided dice")

? ? }

? ? func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {

? ? ? ? ++numberOfTurns

? ? ? ? print("Rolled a \(diceRoll)")

? ? }

? ? func gameDidEnd(game: DiceGame) {

? ? ? ? print("The game lasted for \(numberOfTurns) turns")

? ? }

}

let tracker = DiceGameTracker()

let game = SnakesAndLadders()

game.delegate = tracker

game.play()

//===========================

protocol TextRepresentable {

? ? var textualDescription: String { get }

}

extension Dice: TextRepresentable { ? ? //擴(kuò)展Dice類來采納并符合協(xié)議

? ? var textualDescription: String {

? ? ? ? return "A \(sides)-sided dice"

? ? }

}

let d12 = Dice(sides: 12,generator: LinearCongruentialGenerator())

print(d12.textualDescription)

extension SnakesAndLadders: TextRepresentable {

? ? var textualDescription: String {

? ? ? ? return "A game of Snakes and Ladders with \(finalSquare) squares"

? ? }

}

print(game.textualDescription)

//==============

struct Hamster {

? ? var name: String

? ? var textualDescription: String {

? ? ? ? return "A hamster named \(name)"

? ? }

}

extension Hamster: TextRepresentable {} ? //本身已經(jīng)符合了協(xié)議的所有要求,可通過空擴(kuò)展來采納協(xié)議

let simonTheHamster = Hamster(name: "Simon")

let somethingTextRepresentable: TextRepresentable = simonTheHamster

print(somethingTextRepresentable.textualDescription)

//==================

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

for thing in things {

? ? print(thing.textualDescription)

}

//========================

protocol PrettyTextRepresentable: TextRepresentable {

? ? var prettyTextualDescription: String { get }

}

extension SnakesAndLadders: PrettyTextRepresentable {

? ? //每個(gè) PrettyTextRepresentable 類型同時(shí)也是 TextRepresentable 類型

? ? //所以在 prettyTextualDescription 的實(shí)現(xiàn)中,可以訪問 textualDescription 屬性

? ? var prettyTextualDescription: String {

? ? ? ? var output = textualDescription + ":\n"

? ? ? ? for index in 1...finalSquare {

? ? ? ? ? ? switch board[index] {

? ? ? ? ? ? case let ladder where ladder > 0:

? ? ? ? ? ? ? ? output += "▲ "

? ? ? ? ? ? case let snake where snake < 0:

? ? ? ? ? ? ? ? output += "▼ "

? ? ? ? ? ? default:

? ? ? ? ? ? ? ? output += "○ "

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return output

? ? }

}

print(game.prettyTextualDescription)

//=============================

protocol Named {

? ? var name: String { get }

}

protocol Aged {

? ? var age: Int { get }

}

struct Person1: Named, Aged {

? ? var name: String

? ? var age: Int

}

func wishHappyBirthday(celebrator: protocol<Named, Aged>) { ? ? //同時(shí)采納多個(gè)協(xié)議

? ? print("Happy birthday \(celebrator.name) - you're \(celebrator.age)!")

}

let birthdayPerson = Person1(name: "Malcolm", age: 21)

wishHappyBirthday(birthdayPerson)

//============================

protocol HasArea {

? ? var area: Double { get }

}

class Circle: HasArea {

? ? let pi = 3.1415927

? ? var radius: Double

? ? var area: Double { return pi * radius * radius }

? ? init(radius: Double) { self.radius = radius }

}

class Country: HasArea {

? ? var area: Double

? ? init(area: Double) { self.area = area }

}

class Animal {

? ? var legs: Int

? ? init(legs: Int) { self.legs = legs }

}

let objects: [AnyObject] = [? ? //它們都是類,它們的實(shí)例都可以作為 AnyObject 類型的值

? ? Circle(radius: 2.0),

? ? Country(area: 243_610),

? ? Animal(legs: 4)

]

for object in objects {

? ? if let objectWithArea = object as? HasArea {

? ? ? ? print("Area is \(objectWithArea.area)")

? ? } else {

? ? ? ? print("Something that doesn't have an area")

? ? }

}

//================================

@objc protocol CounterDataSource {

? ? optional func incrementForCount(count: Int) -> Int

? ? optional var fixedIncrement: Int { get }

}

class Counter {

? ? var count = 0

? ? var dataSource: CounterDataSource?

? ? func increment() {

? ? ? ? if let amount = dataSource?.incrementForCount?(count) {

? ? ? ? ? ? count += amount

? ? ? ? } else if let amount = dataSource?.fixedIncrement {

? ? ? ? ? ? count += amount

? ? ? ? }

? ? }

}

class ThreeSource: NSObject, CounterDataSource {

? ? let fixedIncrement = 3

}

var counter = Counter()

counter.dataSource = ThreeSource()

for _ in 1...4 {

? ? counter.increment()

? ? print(counter.count)

}

@objc class TowardsZeroSource: NSObject, CounterDataSource {

? ? func incrementForCount(count: Int) -> Int {

? ? ? ? if count == 0 {

? ? ? ? ? ? return 0

? ? ? ? } else if count < 0 {

? ? ? ? ? ? return 1

? ? ? ? } else {

? ? ? ? ? ? return -1

? ? ? ? }

? ? }

}

counter.count = -4

counter.dataSource = TowardsZeroSource()

for _ in 1...5 {

? ? counter.increment()

? ? print(counter.count)

}

//=============================

//通過協(xié)議擴(kuò)展,所有采納協(xié)議的類型,都能自動(dòng)獲得這個(gè)擴(kuò)展所增加的方法實(shí)現(xiàn),無需任何額外修改:

extension RandomNumberGenerator {

? ? func randomBool() -> Bool {

? ? ? ? return random() > 0.5

? ? }

}

let generator1 = LinearCongruentialGenerator()

print("Here's a random number: \(generator1.random())")

// 打印 “Here's a random number: 0.37464991998171”

print("And here's a random Boolean: \(generator1.randomBool())")

// 打印 “And here's a random Boolean: true”

//=======

extension CollectionType where Generator.Element: TextRepresentable { ? //為協(xié)議的擴(kuò)展添加限制條件

? ? var textualDescription: String {

? ? ? ? let itemsAsText = self.map { $0.textualDescription }

? ? ? ? return "[" + itemsAsText.joinWithSeparator(", ") + "]"

? ? }

}

?

轉(zhuǎn)載于:https://www.cnblogs.com/susufufu/p/5705636.html

總結(jié)

以上是生活随笔為你收集整理的swift学习笔记之-协议的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。