//: Playground - noun: a place where people can play
import UIKit
// # 協(xié)議的語(yǔ)法
// # 屬性要求
// 必須定義為變量屬性,因?yàn)樵诙x時(shí)看上去是個(gè)計(jì)算屬性.
protocol AProtocol {
var mustBeSettable: Int { get set } // 只能是get-set計(jì)算或var存儲(chǔ)屬性
var canBeSettable: Int { get } // 可以是各類屬性.
static var someTypeProperty: Int { get set }
}
protocol FullyNamed {
var fullName: String { get }
}
struct Person: FullyNamed {
var fullName: String
}
let john = Person(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
// # 方法要求
// 方法參數(shù)不能定義默認(rèn)值
protocol RandomNumberGenerator {
func random() -> Double
}
// 線性同余法生成偽隨機(jī)數(shù)
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).truncatingRemainder(dividingBy: m))
return lastRandom / m
}
}
let generator = LinearCongruentialGenerator()
print(generator.random())
print(generator.random())
// # 異變方法要求
protocol Togglable {
mutating func toggle()
}
enum OnOffSwitch: Togglable {
case off, on
mutating func toggle() {
switch self {
case .off:
self = .on
default:
self = .off
}
}
}
var lightSwitch = OnOffSwitch.off
lightSwitch.toggle()
// # 初始化器要求
// 可以使用required, final關(guān)鍵字
protocol SomeProtocol {
init()
}
class SomeSuperClass {
init() {}
}
class SomeSubClass: SomeSuperClass, SomeProtocol {
required override init() {}
}
// 遵循協(xié)議的類型可以使用一個(gè)可失敗的或不可失敗的初始化器滿足一個(gè)可失敗的初始化器要求。不可失敗初始化器要求可以使用一個(gè)不可失敗初始化器或隱式展開的可失敗初始化器滿足同仆。
// # 將協(xié)議作為類型***
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 = Array(repeating: 0, count: finalSquare + 1)
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 += 1
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()
// # 在擴(kuò)展里添加協(xié)議遵循
// 類型已經(jīng)存在的實(shí)例會(huì)在給它的類型擴(kuò)展中添加遵循協(xié)議時(shí)自動(dòng)地采納和遵循這個(gè)協(xié)議萤捆。
protocol TextRepresentable {
var textualDescription: String { get }
}
extension Dice: TextRepresentable {
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)
// 如果一個(gè)類型已經(jīng)遵循了協(xié)議的所有需求,但是還沒有聲明它采納了這個(gè)協(xié)議俗批,可以讓通過(guò)一個(gè)空的擴(kuò)展來(lái)讓它采納這個(gè)協(xié)議
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)
// # 協(xié)議類型的集合
let things: [TextRepresentable] = [game, d12, simonTheHamster]
for thing in things {
print(thing.textualDescription)
}
// # 協(xié)議繼承
protocol PrettyTextRepresentable: TextRepresentable {
var prettyTextualDescription: String { get }
}
extension SnakesAndLadders: PrettyTextRepresentable {
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)
// # 類專用的協(xié)議
protocol SomeClassOnlyProtocol: AnyObject {
// class-only protocol definition goes here.
}
// AnyObject is a protocol to which all classes implicitly conform.
// # 協(xié)議組合
// 用&連接
protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
struct OnePerson: Named, Aged {
var name: String
var age: Int
}
func wishHappyBirthday(to celebrator: Named & Aged) {
print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}
let birthdayPerson = OnePerson(name: "Malcolm", age: 21)
wishHappyBirthday(to: birthdayPerson)
// 也可以包含一個(gè)父類
class Location {
var latitude: Double
var longitude: Double
init(latitude: Double, longitude: Double) {
self.latitude = latitude
self.longitude = longitude
}
}
class City: Location, Named {
var name: String
init(name: String, latitude: Double, longitude: Double) {
self.name = name
super.init(latitude: latitude, longitude: longitude)
}
}
func beginConert(in location: Location & Named) {
print("Hello, \(location.name)!")
}
let seattle = City(name: "Seattle", latitude: 47.6, longitude: -122.3)
beginConert(in: seattle)
// # 協(xié)議遵循的檢查
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 }
}
// Here is a class does not conform to HasArea protocol.
class Animal {
var legs: Int
init(legs: Int) {
self.legs = legs
}
}
// But we can put all three of they into an array...
let objects: [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")
}
}
// # 可選協(xié)議要求
// 允許與Objective-C協(xié)作.@objc 協(xié)議只能被繼承自 Objective-C 類或其他 @objc 類采納俗或。它們不能被結(jié)構(gòu)體或者枚舉采納。
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
class Counter {
var count = 0
var dataSource: CounterDataSource?
func increment() {
if let amount = dataSource?.increment?(forCount: count) {
count += amount // there may or may not be an increment func
} else if let amount = dataSource?.fixedIncrement {
count += amount
}
}
}
// NSObject means this is an Obj-C class
class ThreeSource: NSObject, CounterDataSource {
let fixedIncrement: Int = 3
}
var counter = Counter()
counter.dataSource = ThreeSource()
for _ in 1...4 {
counter.increment()
print(counter.count)
}
// more complicated one
@objc class TowardsZeroSource: NSObject, CounterDataSource {
func increment(forCount 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é)議的實(shí)現(xiàn)添加擴(kuò)展方法和屬性.
extension RandomNumberGenerator {
func randomBool() -> Bool {
return random() > 0.5
}
}
let generatorA = LinearCongruentialGenerator()
print("Here's a random number: \(generatorA.random())")
print("And here's a random Boolean: \(generatorA.randomBool())")
// 注意:提供的只是默認(rèn)實(shí)現(xiàn).如果遵循類型給這個(gè)協(xié)議的要求提供了它自己的實(shí)現(xiàn)岁忘,那么它就會(huì)替代擴(kuò)展中提供的默認(rèn)實(shí)現(xiàn)辛慰。
extension PrettyTextRepresentable {
var prettyTextualDescription: String {
return textualDescription
}
}
// 給協(xié)議擴(kuò)展添加限制.
// trick: where's implement.
extension Collection where Iterator.Element: TextRepresentable {
var textualDescription: String {
// trick: map: returns an array containing the results of mapping the given closure over the sequence’s elements.
let itemsAsText = self.map { $0.textualDescription }
// trick: .joined: make them a String
return "[" + itemsAsText.joined(separator: ", ") + "]"
}
}
let murrayTheHamster = Hamster(name: "Murray")
let morganTheHamster = Hamster(name: "Morgan")
let mauriceTheHamster = Hamster(name: "Maurice")
let hamsters = [murrayTheHamster, morganTheHamster, mauriceTheHamster]
print(hamsters.textualDescription)
// ***父類服從某協(xié)議,則子類也服從該協(xié)議干像,可以用is探測(cè)
21.協(xié)議 Protocols Swift官方文檔——版納的筆記
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門辅愿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)智亮,“玉大人,你說(shuō)我怎么就攤上這事点待±龋” “怎么了?”我有些...
- 文/不壞的土叔 我叫張陵癞埠,是天一觀的道長(zhǎng)状原。 經(jīng)常有香客問(wèn)我,道長(zhǎng)苗踪,這世上最難降的妖魔是什么颠区? 我笑而不...
- 正文 為了忘掉前任,我火速辦了婚禮通铲,結(jié)果婚禮上毕莱,老公的妹妹穿的比我還像新娘。我一直安慰自己颅夺,他們只是感情好朋截,可當(dāng)我...
- 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吧黄,像睡著了一般部服。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拗慨,一...
- 那天廓八,我揣著相機(jī)與錄音,去河邊找鬼胆描。 笑死瘫想,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的昌讲。 我是一名探鬼主播,決...
- 文/蒼蘭香墨 我猛地睜開眼减噪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼短绸!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起筹裕,我...
- 序言:老撾萬(wàn)榮一對(duì)情侶失蹤醋闭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后朝卒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體证逻,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年抗斤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了囚企。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丈咐。...
- 正文 年R本政府宣布辆影,位于F島的核電站,受9級(jí)特大地震影響黍特,放射性物質(zhì)發(fā)生泄漏蛙讥。R本人自食惡果不足惜,卻給世界環(huán)境...
- 文/蒙蒙 一灭衷、第九天 我趴在偏房一處隱蔽的房頂上張望键菱。 院中可真熱鬧,春花似錦今布、人聲如沸经备。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)侵蒙。三九已至,卻和暖如春傅蹂,著一層夾襖步出監(jiān)牢的瞬間纷闺,已是汗流浹背。 一陣腳步聲響...
- 正文 我出身青樓婚夫,卻偏偏與公主長(zhǎng)得像浸卦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子案糙,可洞房花燭夜當(dāng)晚...
推薦閱讀更多精彩內(nèi)容
- 0×1.VTP協(xié)議介紹Cisco交換機(jī)一旦通過(guò)某種方式激活了干線(Trunk)限嫌,這些交換機(jī)會(huì)通過(guò)通告報(bào)文來(lái)指示哪些...
- Block 注: 將時(shí)機(jī)放到自己成員函數(shù)內(nèi)部奢讨,防止出現(xiàn)循環(huán)引用 CustomView.h文件 CustomView...
- 《請(qǐng)抓緊年少輕狂的時(shí)光,談一場(chǎng)轟轟烈烈的戀愛吧》 朋友們扒袖,在你們還正當(dāng)風(fēng)華正茂的年紀(jì)的時(shí)候塞茅,請(qǐng)認(rèn)真仔細(xì)的看一下這條...
- 兩天的時(shí)間讀完,吳軍博士的《智能時(shí)代》僚稿,發(fā)現(xiàn)我讀了好多人工智能方面的書凡桥,對(duì)于“大數(shù)據(jù)”這個(gè)詞有挺多定義。大數(shù)據(jù)到底...