协议的用法
- 语法格式
protocol MyProtocol{
//body
}
- class、struct、enum都可以遵守协议,多个协议,使用逗号分隔
struct Person: Protocol1, Protocol2{
//body
}
-
协议中添加属性
- 协议同时要求一个属性必须
明确
是可读的
或者可读的和可写的
- 属性要求是变量属性,
不能使用let声明
- 协议同时要求一个属性必须
protocol MyProtocol{
var age : Int{ get }
var name : String{get set}
}
- 在协议中定义方法,我们只需要定义当前方法的名称、参数列表和返回值
protocol MyProtocol {
func teach()
static func teach2()
}
struct Person:MyProtocol {
func teach() {
}
static func teach2() {
}
}
- 协议中也可以定义初始化方法,但是必须使用
required
关键字
protocol MyProtocol {
init(age:Int)
}
class Person:MyProtocol {
required init(age:Int){
}
}
-
将协议作为类型
- 作为函数,方法或者初始化程序中的参数类型或返回类型
- 作为常量,变量或属性的类型
- 作为数组,字典或其他容器中项目的类型
```swift
protocol Shape{
var area: Double{ get }
}
class Circle: Shape{
var radious: Double
init(_ radious: Double) {
self.radious = radious
}
var area: Double{
get{
return radious * radious * 3.14
}
}
}
class Rectangle: Shape{
var width, height: Double
init(_ width: Double, _ height: Double) {
self.width = width
self.height = height
}
var area: Double{
get{
return width * height
}
}
}
var circle: Shape = Circle.init(10.0)
var rectangle: Shape = Rectangle.init(10.0, 20.0)
var shapes: [Shape] = [circle, rectangle]
for shape in shapes{
print(shape.area)
}
- 协议默认实现
protocol MyProtocol {
func teach(age:Int)
}
extension MyProtocol{
func teach(age:Int){
}
}
class Person:MyProtocol {
}
- 思考:看一下代码打印是什么?
protocol MyProtocol {
func teach()
}
extension MyProtocol {
func teach() {
print("MyProtocol")
}
}
class MyClass: MyProtocol {
func teach() {
print("MyClass")
}
}
let object: MyProtocol = MyClass()
object.teach()
let object1: MyClass = MyClass()
object1.teach()
- 打印输出
- 那么下面应该输出什么呢?
protocol MyProtocol {
}
extension MyProtocol {
func teach() {
print("MyProtocol")
}
}
class MyClass: MyProtocol {
func teach() {
print("MyClass")
}
}
let object: MyProtocol = MyClass()
object.teach()
let object1: MyClass = MyClass()
object1.teach()
-
打印结果
-
上述的两个打印为什么不一样呢?生成sil代码查看一下调用
- 协议中声明teach方法
⏬
查看一下witness_method
是什么,发现是直接调用
的是类的methodList
中的teach
方法
-
协议中没有声明teach方法
-
witness_table
没有值
小结
witness_method
:通过PWT(协议目击表)获取对应的函数地址class_method
:该指令通过类的函数表来查找函数,基于类的实际类型。
底层分析
根据下述代码,先查看一下两个变量占用内存的大小
- 生成IR代码查看底层逻辑
其中T4main10MyProtocolP
是一个结构体
- 转成swift代码是
24字节
struct protocolData {
var value1: UnsafeRawPointer
var value2: UnsafeRawPointer
var value3: UnsafeRawPointer
var type: UnsafeRawPointer
var pwt: UnsafeRawPointer
}