swift学习笔记之-协议
//協議(Protocols)
?
import UIKit
?
/*協議(Protocols)
? ? 1.協議定義了一個藍圖,規定了用來實現某一特定任務或者功能的方法、屬性,以及其他需要的東西
? ? 2.類、結構體或枚舉都可以采納協議,并為協議定義的這些要求提供具體實現。某個類型能夠滿足某個協議的要求,就可以說該類型“符合”這個協議。
? ? 3.除了采納協議的類型必須實現的要求外,還可以對協議進行擴展,通過擴展來實現一部分要求或者實現一些附加功能,這樣采納協議的類型就能夠使用這些功能。
協議定義語法:? protocol SomeProtocol { // 這里是協議的定義部分 }
協議的采納:擁有父類的類在采納協議時,應該將父類名放在協議名之前,以逗號分隔:
? ? ? ? class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
? ? ? ? ? ? // 這里是類的定義部分
? ? ? ? }
?
屬性要求:
? ? 1.協議可以要求采納協議的類型提供特定名稱和類型的實例屬性或類型屬性。協議不指定屬性是存儲型屬性還是計算型屬性,它只指定屬性的名稱和類型。
? ? 2.協議還指定屬性是只讀的還是可讀可寫的
? ? 3.如果協議要求屬性是可讀可寫的,那么該屬性不能是常量屬性或只讀的計算型屬性。如果協議只要求屬性是只讀的,那么該屬性不僅可以是只讀的,如果代碼需要的話,還可以是可寫的
protocol SomeProtocol {
? ? var mustBeSettable: Int { get set } ? ? //表示屬性是可讀可寫的
? ? static var doesNotNeedToBeSettable: Int { get }? ? ? ? //類型屬性、只讀屬性,static 關鍵字,類類型的還可以使用 class 關鍵字來聲明類型屬性
}
?
方法要求:
? ? 1.協議可以要求采納協議的類型實現某些指定的實例方法或類型方法。這些方法作為協議的一部分,像普通方法一樣放在協議的定義中,但是不需要大括號和方法體。可以在協議中定義具有可變參數的方法,和普通方法的定義方式相同。但是,不支持為協議中的方法的參數提供默認值。
? ? 2.在協議中定義類型方法的時候,總是使用 static 關鍵字作為前綴。當類類型采納協議時,除了 static 關鍵字,還可以使用 class 關鍵字作為前綴
? ? 3.值類型的Mutating 方法要求:若需要在值類型的方法中修改方法所屬的實例,將 mutating 關鍵字作為方法的前綴
?
構造器要求:協議可以要求采納協議的類型實現指定的構造器
? ? 1.你可以在采納協議的類中實現構造器,無論是作為指定構造器,還是作為便利構造器。無論哪種情況,你都必須為類的構造器實現標上 required 修飾符:
? ? 2.使用 required 修飾符可以確保所有子類也必須提供此構造器實現,從而也能符合協議
? ? 3.如果一個子類重寫了父類的指定構造器,并且該構造器滿足了某個協議的要求,那么該構造器的實現需要同時標注 required 和 override 修飾符
?
協議作為類型:
? ? 1.盡管協議本身并未實現任何功能,但是協議可以被當做一個成熟的類型來使用。
? ? 2.協議可以像其他普通類型一樣使用,使用場景如下:
? ? ? ? 1.作為函數、方法或構造器中的參數類型或返回值類型
? ? ? ? 2.作為常量、變量或屬性的類型
? ? ? ? 3.作為數組、字典或其他容器中的元素類型
委托(代理)模式:嵌套
? ? 1.委托是一種設計模式,它允許類或結構體將一些需要它們負責的功能委托給其他類型的實例。
? ? 2.委托模式的實現很簡單:定義協議來封裝那些需要被委托的功能,這樣就能確保采納協議的類型能提供這些功能。
? ? 3.委托模式可以用來響應特定的動作,或者接收外部數據源提供的數據,而無需關心外部數據源的類型
通過擴展采納協議:
? ? 1.即便無法修改源代碼,依然可以通過擴展令已有類型采納并符合協議。擴展可以為已有類型添加屬性、方法、下標腳本以及構造器,因此可以符合協議中的相應要求。通過擴展令已有類型采納并符合協議時,該類型的所有實例也會隨之獲得協議中定義的各項功能。
? ? 2.當一個類型已經符合了某個協議中的所有要求,卻還沒有聲明采納該協議時,可以通過空擴展體的擴展來采納該協議
協議類型的集合:協議類型可以在數組或者字典這樣的集合中使用,所有采納某協議的類型實例,雖然類型各不相同,但都是該協議類型
?
協議的繼承:協議能夠繼承一個或多個其他協議,可以在繼承的協議的基礎上增加新的要求。協議的繼承語法與類的繼承相似,多個被繼承的協議間用逗號分隔:
? ? protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
? ? ? ? // 這里是協議的定義部分
? ? }
類類型專屬協議:在協議的繼承列表中,通過添加 class 關鍵字來限制協議只能被類類型采納,如果嘗試讓結構體或枚舉類型采納該協議,則會導致編譯錯誤。
? ? ? ? protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
? ? ? ? ? ? // 這里是類類型專屬協議的定義部分
? ? ? ? }
?
協議合成:有時候需要同時采納多個協議,你可以將多個協議采用 protocol<SomeProtocol, AnotherProtocol> 這樣的格式進行組合,稱為 協議合成(protocol composition)。你可以在 <> 中羅列任意多個你想要采納的協議,以逗號分隔
?
檢查協議一致性:
? ? 1.你可以使用類型轉換中描述的 is 和 as 操作符來檢查協議一致性,即是否符合某協議,并且可以轉換到指定的協議類型。
? ? 2.檢查和轉換到某個協議類型在語法上和類型的檢查和轉換完全相同:
? ? ? ? is 用來檢查實例是否符合某個協議,若符合則返回 true,否則返回 false。
? ? ? ? as? 返回一個可選值,當實例符合某個協議時,返回類型為協議類型的可選值,否則返回 nil。
? ? ? ? as! 將實例強制向下轉換到某個協議類型,如果強轉失敗,會引發運行時錯誤。
?
可選的協議要求:
? ? 1.協議可以定義可選要求,采納協議的類型可以選擇是否實現這些要求。
? ? 2.在協議中使用 optional 關鍵字作為前綴來定義可選要求。
? ? 3.使用可選要求時(例如,可選的方法或者屬性),它們的類型會自動變成可選的
? ? 4.協議中的可選要求可通過可選鏈式調用來使用,因為采納協議的類型可能沒有實現這些可選要求
? ? 5.可選的協議要求只能用在標記 @objc 特性的協議中。該特性表示協議將暴露給 Objective-C 代碼,詳情參見Using Swift with Cocoa and Objective-C(Swift 2.1)。即使你不打算和 Objective-C 有什么交互,如果你想要指定可選的協議要求,那么還是要為協議加上 @obj 特性。還需要注意的是,標記 @objc 特性的協議只能被繼承自 Objective-C 類的類或者 @objc 類采納,其他類以及結構體和枚舉均不能采納這種協議。
?
協議擴展:
? ? 1.協議可以通過擴展來為采納協議的類型提供屬性、方法以及下標腳本的實現。通過這種方式,你可以基于協議本身來實現這些功能,而無需在每個采納協議的類型中都重復同樣的實現,也無需使用全局函數
? ? 2.提供默認實現:可以通過協議擴展來為協議要求的屬性、方法以及下標腳本提供默認的實現。如果采納協議的類型為這些要求提供了自己的實現,那么這些自定義實現將會替代擴展中的默認實現被使用。
? ? 3.為協議擴展添加限制條件:在擴展協議的時候,可以指定一些限制條件,只有采納協議的類型滿足這些限制條件時,才能獲得協議擴展提供的默認實現。這些限制條件寫在協議名之后,使用 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())") //每執行一次,lastRandom的值就被改變一次
print("And another one: \(generator.random())")
//=====================
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
? ? }
}
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) ? //代理協議
? ? 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 { ? ? //擴展Dice類來采納并符合協議
? ? 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 {} ? //本身已經符合了協議的所有要求,可通過空擴展來采納協議
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 {
? ? //每個 PrettyTextRepresentable 類型同時也是 TextRepresentable 類型
? ? //所以在 prettyTextualDescription 的實現中,可以訪問 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>) { ? ? //同時采納多個協議
? ? 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] = [? ? //它們都是類,它們的實例都可以作為 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)
}
//=============================
//通過協議擴展,所有采納協議的類型,都能自動獲得這個擴展所增加的方法實現,無需任何額外修改:
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 { ? //為協議的擴展添加限制條件
? ? var textualDescription: String {
? ? ? ? let itemsAsText = self.map { $0.textualDescription }
? ? ? ? return "[" + itemsAsText.joinWithSeparator(", ") + "]"
? ? }
}
?
轉載于:https://www.cnblogs.com/susufufu/p/5705636.html
總結
以上是生活随笔為你收集整理的swift学习笔记之-协议的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: warning:This applica
- 下一篇: HDOJ(HDU) 1994 利息计算(