美文网首页
Swift5.1学习随笔之协议Protocol

Swift5.1学习随笔之协议Protocol

作者: SAW_ | 来源:发表于2020-04-30 16:54 被阅读0次

协议Protocol

  • 协议可以用来定义方法、属性、下标声明,协议可以被枚举、结构体、类遵守(多个协议用逗号隔开)
  • 协议中定义方法适合不能有默认参数值
  • 默认情况下,协议中定义的内容必须全部实现
  • 协议中定义属性必须是var
  • 实现协议的属性权限要不小于协议中定义的属性权限
protocol Drawable {
    func draw()
    var x: Int { get set }
    var y: Int { get }
    subscript(index: Int) -> Int { get set }
}
protocol Test1 {}
protocol Test2 {}
protocol Test3 {}
class TestClass: Test1, Test2, Test3 { }
class Personal: Drawable {
    var x: Int = 0
    var y: Int = 0
    func draw() {
        print("Personal draw")
    }
    subscript(index: Int) -> Int {
        get { index }
        set { }
    }
}

协议中的属性

protocol Drawable {
    var x: Int { get set }
    var y: Int { get }
}

协议Drawable中定义了两个变量xy,那么在其他对象中如何实现这两个属性,如果做到实现的时候让x是可读可写的,让y是只读的

  • 用存储属性方式实现,x设置成变量,满足可读可写,y设置成常量,满足只读
class Personal: Drawable {
    var x: Int = 0
    let y: Int = 0
}
  • 用计算属性方式实现,计算属性有getset方法
class Personal: Drawable {
    var x: Int {
        get { 0 }
        set { }
    }
    var y: Int {
        get { 0 }
    }
}

static、class

  • 为了保证通用,协议中必须用static关键字定义类型方法、类型属性、类型下标
protocol Drawable {
    static func draw()
}
//如果允许子类重写,就用class
class Personal: Drawable {
    class func draw() {
        print("Personal draw")
    }
}
//如果不允许子类重写,就用static
class Personal: Drawable {
    static func draw() {
        print("Personal draw")
    }
}

mutating

只有将协议中的实例方法标记为mutating

  • 才允许结构体、枚举的具体实现修改自身内存
  • 类在实现方法时候不需要加mutating,枚举、结构体才需要添加
protocol Drawable {
    mutating func draw()
}

class Size: Drawable {
    var width: Int = 0
    func draw() {
        width = 10
    }
}

struct Point: Drawable {
    var x: Int = 0
    mutating func draw() {
        x = 10
    }
}

init

协议中还可以定义初始化器init

  • final类实现时必须加上required
protocol Drawable {
    init(x: Int, y: Int)
}

class Point: Drawable {
    required init(x: Int, y: Int) { }
}

final class Size: Drawable {
    init(x: Int, y: Int) { }
}

如果从协议实现的初始化器,刚好是重写了父类的指定初始化器

  • 那么这个初始化必须同时加上requiredoverride
protocol Livable {
    init(age: Int)
}

class Person {
    init(age: Int) { }
}

class Student: Person, Livable {
    required override init(age: Int) {
        super.init(age: age)
    }
}

init、init?、init!

  • 协议中定义的init?init!,可以用initinit?init!去实现
  • 协议中定义的init,可以用initinit!去实现
protocol Readable {
    init()
    init?(age: Int)
    init!(num: Int)
}

class Personal: Readable {
    required init() { }
//    required init!() { }
    
    required init?(age: Int) { }
//    required init!(age: Int) { }
//    required init(age: Int) { }
    
    required init!(num: Int) { }
//    required init?(num: Int) { }
//    required init(num: Int) { }
}

协议的继承

一个协议可以继承其他协议

protocol Runnable {
    func run()
}

protocol Livable: Runnable {
    func breath()
}

class Person: Livable {
    func run() {}
    func breath() {}
}

协议组合

协议组合,可以包含1个类类型(最多一个)

protocol Livable { }
protocol Runnable { }
class Personal { }

//接受Personal或者其子类的实例
func fn1(obj: Personal) { }
//接受遵守Livable协议的实例
func fn2(obj: Livable) { }
//接受同时遵守Runnable、Livable协议的实例
func fn3(obj: Livable & Runnable) { }
//接受同时遵守Runnable、Livable协议,并且是Personal或者其子类的实例
func fn4(obj: Personal & Livable & Runnable) { }
typealias RealPerson = Personal & Livable & Runnable
//接受同时遵守Runnable、Livable协议,并且是Personal或者其子类的实例
func fn(obj: RealPerson) { }

CaseInterable

让枚举遵守CaseInterable协议,可以实现遍历枚举值

enum Season: CaseIterable {
    case spring, summer, autumn, winter
}
let seasons = Season.allCases

print(seasons) // [SwiftDDDDD.Season.spring, SwiftDDDDD.Season.summer, SwiftDDDDD.Season.autumn, SwiftDDDDD.Season.winter]

for season in seasons {
    print(season)
} // spring summer autumn winter

CustomStringConvertible

遵守CustomStringConvertible协议,可以自定义实例的打印字符串
必须实现

var description: String 
class Car: CustomStringConvertible {
    var name: String
    var price: Double
    init(name: String, price: Double) {
        self.name = name
        self.price = price
    }
    var description: String {
        "name = \(name), price = \(price)"
    }
}

var c = Car(name: "三轮车", price: 100.1)
print(c) // name = 三轮车, price = 100.1

Any、AnyObject

swift提供了2种特殊的类型:AnyAnyObject

  • Any:可以代表任意类型(枚举、类、结构体、也包括函数类型)
  • AnyObject:可以代表任意类型(在协议后面写上:AnyObject代表只有类能遵守这个协议)

举例子🌰1

protocol Runnable { }

class Personal: Runnable { }

struct Size: Runnable {}
protocol Runnable: AnyObject { }

class Personal: Runnable { }

//报错:Non-class type 'Size' cannot conform to class protocol 'Runnable'
struct Size: Runnable {}

举例子🌰2

var stu: Any = 10
stu = "jack"
stu = Student()
var stu: AnyObject = 10 //报错:Value of type 'Int' does not conform to specified type 'AnyObject'
stu = "jack" //报错:lue of type 'String' does not conform to 'AnyObject' in assignment
stu = Student()

举个例子🌰3:创建1个能存放任意类型的数组

var data = Array<Any>()
data.append(1)
data.append(3.14)
data.append(Person())
data.append("jack")
data.append({10})
data.append(true)

相关文章

  • Swift5.1学习随笔之协议Protocol

    协议Protocol 协议可以用来定义方法、属性、下标声明,协议可以被枚举、结构体、类遵守(多个协议用逗号隔开) ...

  • HTTP协议的初步学习

    HTTP协议的学习 协议的概述 超文本传输协议(英文:HyperText Transfer Protocol,缩写...

  • ICMP

    网际协议IP(3)之网际控制报文协议ICMP(Internet Control Message Protocol)...

  • Signal protocol

    端对端加密通讯协议Signal protocol 学习

  • HTTP协议之状态码详解

    HTTP协议之状态码详解 Hypertext Transfer Protocol -- HTTP/1.1

  • Swift之协议(protocol)

    协议(protocol)规定了用来实现某一特定功能所必需的方法和属性。任意能够满足协议要求的类型被称为遵循(con...

  • 《Swift从入门到精通》(十八):协议

    协议(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 协议语法示例protocol Some...

  • protocol (Swift3.x)

    Swift中 protocol的学习 //扩展标准库/定义属于个人的协议的学习 //---------------...

  • Protocol

    使用protocol定义协议//Protocol Syntaxprotocol SomeProtocol { }...

  • Swift5.1学习随笔之指针

    Swift中也有专门的指针类型,这些都被定义为Unsafe(不安全的),常见的有以下4种类型 UnsafePoin...

网友评论

      本文标题:Swift5.1学习随笔之协议Protocol

      本文链接:https://www.haomeiwen.com/subject/bpctghtx.html