- 協議語法
protocol protocol1 {
}
protocol protocol2 {
}
class Test {
}
class Test1: Test, protocol1, protocol2 {
}
複製代碼
- 屬性要求
- 必定是var關鍵子的屬性
- 屬性的名字要一致
- 屬性的類型要一致
- 若是協議是get只讀屬性,那麼協議的實現能夠是隻讀屬性,也能夠是可讀寫屬性。
- 若是協議是get,set屬性,那麼協議的實行必須是可讀寫屬性。
protocol FullName {
var fullName: String {get}
}
class Person: FullName {
var name: String
var preName: String?
init(name: String, preName: String? = nil) {
self.name = name
self.preName = preName
}
var fullName: String {
var str = preName ?? ""
if str.isEmpty {
str = name
}else{
str = str + " " + name
}
return str
}
}
let a = Person(name: "小明", preName: "王")
print(a.fullName)
複製代碼
- 方法要求
- 協議能夠定義實例方法或者類型方法,類型方法必須用static關鍵字。
- 協議的遵循者要實現相應的實例方法或者類型方法,類型方法能夠用static,class關鍵字
- 有參數就在協議裏寫上參數,有返回值就寫上返回值,沒有就不寫。
protocol Funcation {
func sum(one: Double, two: Double) -> Double
static func addOne(num: Int) -> Int
}
class Test: Funcation {
func sum(one: Double, two: Double) -> Double {
return one + two
}
static func addOne(num: Int) -> Int {
return num + 1
}
}
複製代碼
- 異變方法要求
- 協議要在func前用mutating關鍵字修飾。
- 協議實現若是是值類型(枚舉類型,結構體)也要用mutating修飾。若是是類就不須要這個關鍵字了。
protocol ChangeProtocol {
mutating func change()
}
enum Switch: String, ChangeProtocol {
case on, off
mutating func change() {
switch self {
case .on:
self = .off
case .off:
self = .on
}
}
}
class Test: ChangeProtocol {
func change() {
}
}
var a = Switch.on
a.change()
print(a)
複製代碼
- 構造器要求
protocol SomeProtocol {
init()
}
class SomeClass {
init() {
}
}
class SubSomeClass: SomeClass, SomeProtocol {
required override init(){
}
}
class SubSomeClass1: SomeProtocol {
required init(){
}
}
class SubSomeClass2: SubSomeClass1 {
required init(){
}
}
複製代碼
- 可失敗構造器要求
- 協議中定義了可失敗構造器,那麼協議的遵照者能夠實現非可失敗構造器,也能夠實現可失敗構造器。
- 協議中定義了不可失敗構造器,那麼協議的遵照者要用非可失敗構造器去實現。
protocol SomeProtocol {
init?()
}
class SomeClass: SomeProtocol {
required init() {
}
// required init()? {
//
// }
}
複製代碼
- 協議做爲類型
import UIKit
protocol RandomNum {
func random() -> Double
}
struct Dice {
var sides: Int
var random: RandomNum
init(sides: Int, random: RandomNum) {
self.sides = sides
self.random = random
}
func roll() -> Int{
return Int(self.random.random() * Double(self.sides)) + 1
}
}
struct RandomStruct: RandomNum {
func random() -> Double {
let Y = arc4random_uniform(100 - 0) + 0
return Double(Y % 10) * 0.1
}
}
let dice = Dice(sides: 6, random: RandomStruct())
print(dice.roll())
複製代碼
- 委託
//1. 委託
protocol RandomDevice {
func roll() -> Double
}
class Dice {
var sides: Int
var randomDevice: RandomDevice
init(sides: Int, randomDevice: RandomDevice) {
self.sides = sides
self.randomDevice = randomDevice
}
func playDiceOnce() -> Int {
return Int(randomDevice.roll() * Double(sides)) + 1
}
}
class LineRandomDevice: RandomDevice {
func roll() -> Double {
return Double((arc4random_uniform(100 - 0) + 0) % 10) * 0.1
}
}
protocol DiceGame {
var dice: Dice {get}
func play()
}
protocol DiceGameTrack {
func diceGameDidStart(diceGame: DiceGame)
func diceGamePlay(diceGame: DiceGame, number: Int)
func diceGameDidEnd(diceGame: DiceGame)
}
class SnakesAndLaddersGame: DiceGame {
var finalStep = 25
var board: [Int]
var delegate: DiceGameTrack?
var squire = 0
init() {
board = Array(repeating: 0, count: finalStep + 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 dice: Dice = Dice(sides: 6, randomDevice: LineRandomDevice())
func play() {
self.delegate?.diceGameDidStart(diceGame: self)
loop: while squire != finalStep {
let number = dice.playDiceOnce()
self.delegate?.diceGamePlay(diceGame: self, number: number)
switch number + squire{
case finalStep:
break loop
case let newValue where newValue > finalStep:
continue loop
default:
squire += number
squire += board[squire]
}
}
self.delegate?.diceGameDidEnd(diceGame: self)
}
}
class SnakesAndLaddersDiceGameTrack: DiceGameTrack {
var turns = 0
func diceGameDidStart(diceGame: DiceGame) {
print("\(diceGame) is starting")
}
func diceGamePlay(diceGame: DiceGame, number: Int) {
turns += 1
print("\(diceGame) roll is \(number) playing...")
}
func diceGameDidEnd(diceGame: DiceGame) {
print("\(diceGame) is end \(turns)turns")
}
}
var a = SnakesAndLaddersGame()
var b = SnakesAndLaddersDiceGameTrack()
a.delegate = b
a.play()
複製代碼
- 經過擴展來遵照協議
//2. 經過擴展遵照協議
protocol Despration {
func despration()
}
extension SnakesAndLaddersGame: Despration {
func despration() {
print("fineSquire is \(self.finalStep)")
}
}
a.despration()
複製代碼
- 有條件的遵照協議
- 數組中map方法 $0表明每一個元素。最後map方法返回一個元素自定義的數組。
- 數組中的joined方法,只有當數組中的每一個元素都是String類型纔可使用。
//3. 有條件的遵循協議
extension Dice: Despration {
func despration() -> String{
return "A \(sides)-sided dice"
}
}
extension Array: Despration where Element: Despration {
func despration() -> String{
let itemsAsText = self.map { $0.despration() }
return ("[" + itemsAsText.joined(separator: ", ") + "]")
}
}
var d6 = Dice(sides: 6, randomDevice: LineRandomDevice())
var d12 = Dice(sides: 12, randomDevice: LineRandomDevice())
let myDice = [d6, d12]
print(myDice.despration())
複製代碼
- 空遵照
- 當一個類型寫了全部協議的實現,知足了這個協議的全部要求,可是沒有顯式的遵照,這時候是不遵照的。
- 這個時候咱們能夠經過擴展將這個類型遵照這個協議而且大括號裏不寫內容。
protocol Description {
var description:String{get}
func test() -> String
}
struct Test{
var name: String
var description: String{
return "name is \(name)"
}
func test() -> String {
return "test"
}
}
extension Test:Description{}
var a = Test(name: "小明")
print(a.description)
var b: Description = a
print(b.test())
複製代碼
- 協議類型集合
protocol Description {
var description: String{get}
}
class Animal: Description {
var description: String{
return "Animal type"
}
}
class Dog: Description {
var description: String{
return "Dog type"
}
}
var a: [Description] = [Animal(), Dog()]
for item in a {
print(item.description)
}
複製代碼
- 協議的繼承
protocol Description {
var description: String{get}
}
protocol Test: Description {
var test: String{get}
}
class Animal: Test {
var description: String{
return "Animal type"
}
var test: String{
return "test"
}
}
var aAnimal = Animal()
print(aAnimal.test)
print(aAnimal.description)
複製代碼
- 類專屬協議
protocol Description {
var description: String{get}
}
protocol Test: AnyObject, Description {
var test: String{get}
}
//下邊結構體將會報錯
struct Dog: Test {
var description: String{
return "Dog type"
}
var test: String{
return "test"
}
}
class Animal: Test {
var description: String{
return "Animal type"
}
var test: String{
return "test"
}
}
var aAnimal = Animal()
print(aAnimal.test)
print(aAnimal.description)
複製代碼
- 協議合成
protocol Name {
var name: String{get}
}
protocol Age {
var age: Int{get}
}
struct Person: Name, Age {
var name: String
var age: Int
}
func description(person: Name & Age){
print("name is \(person.name) age is \(person.age)")
}
description(person: Person(name: "小明", age: 23))
複製代碼
- 判斷是遵照了哪一種協議
- as? : 用來判斷是否遵照了某個協議,若是沒遵照就返回nil,若是遵照了,就返回這個協議。
- as!和 as?同樣可是有可能觸發運行時錯誤。
protocol AreaProtocol {
var area: Double {get}
}
class Circle: AreaProtocol {
let pi = 3.1415926
var ridus: Double
var area: Double {
return pi * ridus * ridus
}
init(ridus: Double) {
self.ridus = ridus
}
}
class Country: AreaProtocol {
var area: Double
init(area: Double) {
self.area = area
}
}
class Animal {
var legs: Int
init(legs: Int) {
self.legs = legs
}
}
var objs: [AnyObject] = [
Circle(ridus: 5.0),
Country(area: 1300),
Animal(legs: 4)
]
for item in objs {
if let areaPro = item as? AreaProtocol {
print("area = \(areaPro.area)")
}else{
print("no area")
}
}
複製代碼
- 可選協議要求
- @objc用在協議前面
- @objc optional用在屬性和方法前面
- 這種代表只有oc的類才能夠遵照該協議。
import UIKit
@objc protocol CountDataSource {
@objc optional func incerment(count: Int) -> Int
@objc optional var countIncerment: Int{get}
}
class Count {
var total = 0
var dataSource: CountDataSource?
func increment(){
if let amount = dataSource?.incerment?(count: total){
total += amount
}else if let amount = dataSource?.countIncerment{
total += amount
}
}
}
class CountObj: NSObject, CountDataSource{
var countIncerment: Int{
return 3
}
}
//var a = Count()
//a.dataSource = CountObj()
//for _ in 1...4 {
// a.increment()
// print(a.total)
//}
class ZeroSource: NSObject, CountDataSource {
func incerment(count: Int) -> Int {
switch count {
case 0:
return 0
case let cot where cot > 0:
return -1
case let cot where cot < 0:
return 1
default:
return 0
}
}
}
var b = Count()
b.dataSource = ZeroSource()
b.total = -4
for _ in 1...5{
b.increment()
print(b.total)
}
複製代碼
- 協議的擴展
- 能夠給協議擴展計算屬性,和方法。
- 被擴展的協議是可選的協議了,在類裏面能夠直接使用。
import UIKit
protocol TestProtocol {
func random() -> Double
}
extension TestProtocol {
var probability: Bool {
return random() >= 0.5
}
}
class TestClass: TestProtocol {
func random() -> Double {
let num = arc4random_uniform(100 - 0) + 0
let count = Double(num % 10) * 0.1
print(count)
return count
}
}
var a = TestClass()
print(a.probability)
複製代碼
- 爲協議擴展添加約束條件
extension Collection where Element: Equatable{
func allEqual() -> Bool {
for item in self {
if item != self.first {
return false
}
}
return true
}
}
var a = [1,1,1,1,1]
var b = [1,1,1,1,1]
var c = [1,1,1,1,1,2]
print(a.allEqual())
print(b.allEqual())
print(c.allEqual())
複製代碼
- 總結
- 操做符
- as
- as用來向上轉型,如dogObj as Animal
- as用來消除可選類型的警報,如dogObj as Any
- as?
- 用來向下轉型,animalObj as?Dog。
- 用來判斷是否遵照某個協議,areaObj as? AreaProtocol
- as!
- 用來向下轉型,animalObj as?Dog。可能觸發運行時錯誤
- 用來判斷是否遵照某個協議,areaObj。可能觸發運行時錯誤
- is
- 用來判斷某個對象是否屬於某個類,dogObj is Dog
- == 判斷是否兩個值至關, === 判斷是否兩個引用是同一個地址。
- 協議
- 當咱們須要用戶自定義操做時候每每用協議進行委託。如咱們本身封裝了一個模塊,模塊內部有tableView,這時候咱們要用戶自定義cell供咱們模塊內部使用,這時候我麼能夠用協議進行委託。咱們定義一組協議,而後模塊內部定義一個這種協議類型的對象,而後用這個對象的協議的方法。最後讓用戶去遵照這個協議,實現協議的內部方法,返回自定義的Cell。並將模塊的對象進行委託便可。
- 做爲回調。
- 封裝一組功能,對類進行加強。如咱們能夠對應一組協議,而後讓類去遵照這個協議,在實現協議的方法。這個過程實際上是對這個類的功能加強,而且條理更清晰。