iOS开发-Swift进阶之协议Protocol!

swift进阶总汇

本文主要分析protocol的用法及底层存储结构

协议的基本用法

  • 【语法格式】:协议的语法格式
//协议的语法格式
protocol MyProtocol {
    //body
}
  • class、struct、enum都可以遵守协议,如果需要遵守多个协议,可以使用逗号分隔
//1-2、class、struct、enum都可以遵守协议,如果需要遵守多个协议,可以使用逗号分隔
struct CJLTeacher: Protocol1, Protocol2 {
    //body
}
  • 如果class中有superClass,一般是放在遵守的协议之前
//1-3、如果class中有superClass,一般是放在遵守的协议之前
struct CJLTeacher: NSObject, Protocol1, Protocol2 {
    //body
}

协议中添加属性

  • 协议中可以添加属性,但是需要注意一下几点:

  • 1、协议同时要求一个属性必须明确是可读的/可读可写的

  • 属性要求定义为变量属性,即使用var而不是let

protocol CJLTest {
    var age: Int {get set}
}

协议中定义方法

  • 在协议中定义方法,只需要定义当前方法的名称、参数列表和返回值

  • 在具体的类中遵守协议,并实现协议中的方法

protocol MyProtocol {
    func doSomething()
    static func teach()
}
class CJLTeacher: MyProtocol{
    func doSomething() {
        print("CJLTeacher doSomething")
    }
    
    static func teach() {
        print("teach")
    }
}
var t = CJLTeacher()
t.doSomething()
CJLTeacher.teach()
  • 协议中也可以定义初始化方法,当实现初始化器时,必须使用required关键字
protocol MyProtocol {
    init(age: Int)
}
class CJLTeacher: MyProtocol{
    var age: Int
    required init(age: Int) {
        self.age = age
    }
}
  • 如果一个协议只能被实现,需要协议继承自AnyObject。如果此时结构体遵守该协议,会报错

协议进阶 - 将协议作为类型

协议除了上述的基本用法,还有以下几种用法:

  • 1、作为函数、方法或者初始化程序中的参数类型或者返回值

  • 2、作为常量、变量或属性的类型

  • 3、作为数组、字典或其他容器中项目的类型

通过继承基类实现
下面一段代码的打印结果是什么?(通过继承基类实现)

class Shape{
    var area: Double{
        get{
            return 0
        }
    }
}
class Circle: Shape{
    var radius: Double
   
    init(_ radius: Double) {
        self.radius = radius
    }
    
    override var area: Double{
        get{
            return radius * radius * 3.14
        }
    }
}
class Rectangle: Shape{
    var width, height: Double
    init(_ width: Double, _ height: Double) {
        self.width = width
        self.height = height
    }
    
    override 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)
}

<!--打印结果-->
314.0
200.0

对于数组来说,当前的大小是固定的,因为当前存放的都是引用类型(即占8字节),其存储结构如下所示

通过协议实现

作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS开发交流群:130 595 548,不管你是小白还是大牛都欢迎入驻 ,让我们一起进步,共同发展!(群内会免费提供一些群主收藏的免费学习书籍资料以及整理好的几百道面试题和答案文档!)

  • 上述代码的实现是通过继承基类,即基类中的area必须有一个默认实现,也可以通过协议来替代当前代码的书写方式
//2-2、通过协议实现:area必须有一个默认实现
protocol Shape {
    var area: Double {get}
}
class Circle: Shape{
    var radius: Double

    init(_ radius: Double) {
        self.radius = radius
    }

    var area: Double{
        get{
            return radius * radius * 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)
}

<!--打印结果-->
314.0
200.0

当数组中的元素指定的Shape是类时,数组中存储的都是引用类型的地址,那么问题来了,如果数组指定的Shape是一个协议时,数组中存储的是什么?

  • 如果Shape协议提供了一个默认实现,此时的打印是什么?
protocol Shape {
}
extension Shape{
    var area: Double {
        get{return 0}
    }
}
class Circle: Shape{
    var radius: Double

    init(_ radius: Double) {
        self.radius = radius
    }

    var area: Double{
        get{
            return radius * radius * 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 = Circl
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值