swift学习笔记之-协议
//協(xié)議(Protocols)
?
import UIKit
?
/*協(xié)議(Protocols)
? ? 1.協(xié)議定義了一個(gè)藍(lán)圖,規(guī)定了用來(lái)實(shí)現(xiàn)某一特定任務(wù)或者功能的方法、屬性,以及其他需要的東西
? ? 2.類(lèi)、結(jié)構(gòu)體或枚舉都可以采納協(xié)議,并為協(xié)議定義的這些要求提供具體實(shí)現(xiàn)。某個(gè)類(lèi)型能夠滿(mǎn)足某個(gè)協(xié)議的要求,就可以說(shuō)該類(lèi)型“符合”這個(gè)協(xié)議。
? ? 3.除了采納協(xié)議的類(lèi)型必須實(shí)現(xiàn)的要求外,還可以對(duì)協(xié)議進(jìn)行擴(kuò)展,通過(guò)擴(kuò)展來(lái)實(shí)現(xiàn)一部分要求或者實(shí)現(xiàn)一些附加功能,這樣采納協(xié)議的類(lèi)型就能夠使用這些功能。
協(xié)議定義語(yǔ)法:? protocol SomeProtocol { // 這里是協(xié)議的定義部分 }
協(xié)議的采納:擁有父類(lèi)的類(lèi)在采納協(xié)議時(shí),應(yīng)該將父類(lèi)名放在協(xié)議名之前,以逗號(hào)分隔:
? ? ? ? class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
? ? ? ? ? ? // 這里是類(lèi)的定義部分
? ? ? ? }
?
屬性要求:
? ? 1.協(xié)議可以要求采納協(xié)議的類(lèi)型提供特定名稱(chēng)和類(lèi)型的實(shí)例屬性或類(lèi)型屬性。協(xié)議不指定屬性是存儲(chǔ)型屬性還是計(jì)算型屬性,它只指定屬性的名稱(chēng)和類(lèi)型。
? ? 2.協(xié)議還指定屬性是只讀的還是可讀可寫(xiě)的
? ? 3.如果協(xié)議要求屬性是可讀可寫(xiě)的,那么該屬性不能是常量屬性或只讀的計(jì)算型屬性。如果協(xié)議只要求屬性是只讀的,那么該屬性不僅可以是只讀的,如果代碼需要的話(huà),還可以是可寫(xiě)的
protocol SomeProtocol {
? ? var mustBeSettable: Int { get set } ? ? //表示屬性是可讀可寫(xiě)的
? ? static var doesNotNeedToBeSettable: Int { get }? ? ? ? //類(lèi)型屬性、只讀屬性,static 關(guān)鍵字,類(lèi)類(lèi)型的還可以使用 class 關(guān)鍵字來(lái)聲明類(lèi)型屬性
}
?
方法要求:
? ? 1.協(xié)議可以要求采納協(xié)議的類(lèi)型實(shí)現(xiàn)某些指定的實(shí)例方法或類(lèi)型方法。這些方法作為協(xié)議的一部分,像普通方法一樣放在協(xié)議的定義中,但是不需要大括號(hào)和方法體。可以在協(xié)議中定義具有可變參數(shù)的方法,和普通方法的定義方式相同。但是,不支持為協(xié)議中的方法的參數(shù)提供默認(rèn)值。
? ? 2.在協(xié)議中定義類(lèi)型方法的時(shí)候,總是使用 static 關(guān)鍵字作為前綴。當(dāng)類(lèi)類(lèi)型采納協(xié)議時(shí),除了 static 關(guān)鍵字,還可以使用 class 關(guān)鍵字作為前綴
? ? 3.值類(lèi)型的Mutating 方法要求:若需要在值類(lèi)型的方法中修改方法所屬的實(shí)例,將 mutating 關(guān)鍵字作為方法的前綴
?
構(gòu)造器要求:協(xié)議可以要求采納協(xié)議的類(lèi)型實(shí)現(xiàn)指定的構(gòu)造器
? ? 1.你可以在采納協(xié)議的類(lèi)中實(shí)現(xiàn)構(gòu)造器,無(wú)論是作為指定構(gòu)造器,還是作為便利構(gòu)造器。無(wú)論哪種情況,你都必須為類(lèi)的構(gòu)造器實(shí)現(xiàn)標(biāo)上 required 修飾符:
? ? 2.使用 required 修飾符可以確保所有子類(lèi)也必須提供此構(gòu)造器實(shí)現(xiàn),從而也能符合協(xié)議
? ? 3.如果一個(gè)子類(lèi)重寫(xiě)了父類(lèi)的指定構(gòu)造器,并且該構(gòu)造器滿(mǎn)足了某個(gè)協(xié)議的要求,那么該構(gòu)造器的實(shí)現(xiàn)需要同時(shí)標(biāo)注 required 和 override 修飾符
?
協(xié)議作為類(lèi)型:
? ? 1.盡管協(xié)議本身并未實(shí)現(xiàn)任何功能,但是協(xié)議可以被當(dāng)做一個(gè)成熟的類(lèi)型來(lái)使用。
? ? 2.協(xié)議可以像其他普通類(lèi)型一樣使用,使用場(chǎng)景如下:
? ? ? ? 1.作為函數(shù)、方法或構(gòu)造器中的參數(shù)類(lèi)型或返回值類(lèi)型
? ? ? ? 2.作為常量、變量或?qū)傩缘念?lèi)型
? ? ? ? 3.作為數(shù)組、字典或其他容器中的元素類(lèi)型
委托(代理)模式:嵌套
? ? 1.委托是一種設(shè)計(jì)模式,它允許類(lèi)或結(jié)構(gòu)體將一些需要它們負(fù)責(zé)的功能委托給其他類(lèi)型的實(shí)例。
? ? 2.委托模式的實(shí)現(xiàn)很簡(jiǎn)單:定義協(xié)議來(lái)封裝那些需要被委托的功能,這樣就能確保采納協(xié)議的類(lèi)型能提供這些功能。
? ? 3.委托模式可以用來(lái)響應(yīng)特定的動(dòng)作,或者接收外部數(shù)據(jù)源提供的數(shù)據(jù),而無(wú)需關(guān)心外部數(shù)據(jù)源的類(lèi)型
通過(guò)擴(kuò)展采納協(xié)議:
? ? 1.即便無(wú)法修改源代碼,依然可以通過(guò)擴(kuò)展令已有類(lèi)型采納并符合協(xié)議。擴(kuò)展可以為已有類(lèi)型添加屬性、方法、下標(biāo)腳本以及構(gòu)造器,因此可以符合協(xié)議中的相應(yīng)要求。通過(guò)擴(kuò)展令已有類(lèi)型采納并符合協(xié)議時(shí),該類(lèi)型的所有實(shí)例也會(huì)隨之獲得協(xié)議中定義的各項(xiàng)功能。
? ? 2.當(dāng)一個(gè)類(lèi)型已經(jīng)符合了某個(gè)協(xié)議中的所有要求,卻還沒(méi)有聲明采納該協(xié)議時(shí),可以通過(guò)空擴(kuò)展體的擴(kuò)展來(lái)采納該協(xié)議
協(xié)議類(lèi)型的集合:協(xié)議類(lèi)型可以在數(shù)組或者字典這樣的集合中使用,所有采納某協(xié)議的類(lèi)型實(shí)例,雖然類(lèi)型各不相同,但都是該協(xié)議類(lèi)型
?
協(xié)議的繼承:協(xié)議能夠繼承一個(gè)或多個(gè)其他協(xié)議,可以在繼承的協(xié)議的基礎(chǔ)上增加新的要求。協(xié)議的繼承語(yǔ)法與類(lèi)的繼承相似,多個(gè)被繼承的協(xié)議間用逗號(hào)分隔:
? ? protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
? ? ? ? // 這里是協(xié)議的定義部分
? ? }
類(lèi)類(lèi)型專(zhuān)屬協(xié)議:在協(xié)議的繼承列表中,通過(guò)添加 class 關(guān)鍵字來(lái)限制協(xié)議只能被類(lèi)類(lèi)型采納,如果嘗試讓結(jié)構(gòu)體或枚舉類(lèi)型采納該協(xié)議,則會(huì)導(dǎo)致編譯錯(cuò)誤。
? ? ? ? protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
? ? ? ? ? ? // 這里是類(lèi)類(lèi)型專(zhuān)屬協(xié)議的定義部分
? ? ? ? }
?
協(xié)議合成:有時(shí)候需要同時(shí)采納多個(gè)協(xié)議,你可以將多個(gè)協(xié)議采用 protocol<SomeProtocol, AnotherProtocol> 這樣的格式進(jìn)行組合,稱(chēng)為 協(xié)議合成(protocol composition)。你可以在 <> 中羅列任意多個(gè)你想要采納的協(xié)議,以逗號(hào)分隔
?
檢查協(xié)議一致性:
? ? 1.你可以使用類(lèi)型轉(zhuǎn)換中描述的 is 和 as 操作符來(lái)檢查協(xié)議一致性,即是否符合某協(xié)議,并且可以轉(zhuǎn)換到指定的協(xié)議類(lèi)型。
? ? 2.檢查和轉(zhuǎn)換到某個(gè)協(xié)議類(lèi)型在語(yǔ)法上和類(lèi)型的檢查和轉(zhuǎn)換完全相同:
? ? ? ? is 用來(lái)檢查實(shí)例是否符合某個(gè)協(xié)議,若符合則返回 true,否則返回 false。
? ? ? ? as? 返回一個(gè)可選值,當(dāng)實(shí)例符合某個(gè)協(xié)議時(shí),返回類(lèi)型為協(xié)議類(lèi)型的可選值,否則返回 nil。
? ? ? ? as! 將實(shí)例強(qiáng)制向下轉(zhuǎn)換到某個(gè)協(xié)議類(lèi)型,如果強(qiáng)轉(zhuǎn)失敗,會(huì)引發(fā)運(yùn)行時(shí)錯(cuò)誤。
?
可選的協(xié)議要求:
? ? 1.協(xié)議可以定義可選要求,采納協(xié)議的類(lèi)型可以選擇是否實(shí)現(xiàn)這些要求。
? ? 2.在協(xié)議中使用 optional 關(guān)鍵字作為前綴來(lái)定義可選要求。
? ? 3.使用可選要求時(shí)(例如,可選的方法或者屬性),它們的類(lèi)型會(huì)自動(dòng)變成可選的
? ? 4.協(xié)議中的可選要求可通過(guò)可選鏈?zhǔn)秸{(diào)用來(lái)使用,因?yàn)椴杉{協(xié)議的類(lèi)型可能沒(méi)有實(shí)現(xiàn)這些可選要求
? ? 5.可選的協(xié)議要求只能用在標(biāo)記 @objc 特性的協(xié)議中。該特性表示協(xié)議將暴露給 Objective-C 代碼,詳情參見(jiàn)Using Swift with Cocoa and Objective-C(Swift 2.1)。即使你不打算和 Objective-C 有什么交互,如果你想要指定可選的協(xié)議要求,那么還是要為協(xié)議加上 @obj 特性。還需要注意的是,標(biāo)記 @objc 特性的協(xié)議只能被繼承自 Objective-C 類(lèi)的類(lèi)或者 @objc 類(lèi)采納,其他類(lèi)以及結(jié)構(gòu)體和枚舉均不能采納這種協(xié)議。
?
協(xié)議擴(kuò)展:
? ? 1.協(xié)議可以通過(guò)擴(kuò)展來(lái)為采納協(xié)議的類(lèi)型提供屬性、方法以及下標(biāo)腳本的實(shí)現(xiàn)。通過(guò)這種方式,你可以基于協(xié)議本身來(lái)實(shí)現(xiàn)這些功能,而無(wú)需在每個(gè)采納協(xié)議的類(lèi)型中都重復(fù)同樣的實(shí)現(xiàn),也無(wú)需使用全局函數(shù)
? ? 2.提供默認(rèn)實(shí)現(xiàn):可以通過(guò)協(xié)議擴(kuò)展來(lái)為協(xié)議要求的屬性、方法以及下標(biāo)腳本提供默認(rèn)的實(shí)現(xiàn)。如果采納協(xié)議的類(lèi)型為這些要求提供了自己的實(shí)現(xiàn),那么這些自定義實(shí)現(xiàn)將會(huì)替代擴(kuò)展中的默認(rèn)實(shí)現(xiàn)被使用。
? ? 3.為協(xié)議擴(kuò)展添加限制條件:在擴(kuò)展協(xié)議的時(shí)候,可以指定一些限制條件,只有采納協(xié)議的類(lèi)型滿(mǎn)足這些限制條件時(shí),才能獲得協(xié)議擴(kuò)展提供的默認(rèn)實(shí)現(xiàn)。這些限制條件寫(xiě)在協(xié)議名之后,使用 where 子句來(lái)描述
*/
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é)議類(lèi)型
? ? 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類(lèi)來(lái)采納并符合協(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é)議的所有要求,可通過(guò)空擴(kuò)展來(lái)采納協(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 類(lèi)型同時(shí)也是 TextRepresentable 類(lèi)型
? ? //所以在 prettyTextualDescription 的實(shí)現(xiàn)中,可以訪(fǎng)問(wè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] = [? ? //它們都是類(lèi),它們的實(shí)例都可以作為 AnyObject 類(lèi)型的值
? ? 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)
}
//=============================
//通過(guò)協(xié)議擴(kuò)展,所有采納協(xié)議的類(lèi)型,都能自動(dòng)獲得這個(gè)擴(kuò)展所增加的方法實(shí)現(xiàn),無(wú)需任何額外修改:
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学习笔记之-协议的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: warning:This applica
- 下一篇: Linux kill 杀死指定进程