前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >swift 协议

swift 协议

作者头像
xy_ss
发布2023-11-22 09:16:15
1630
发布2023-11-22 09:16:15
举报
文章被收录于专栏:浮躁的喧嚣

协议规定了用来实现某一特定功能所必需的方法和属性

协议语法

代码语言:javascript
复制
protocol SomeProtocol {
    // 这里是协议的定义部分
}

//拥有父类的类在遵循协议时,应该将父类名放在协议名之前
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
    // 这里是类的定义部分
}

对属性、方法的规定

  • 协议中的只能用var来声明变量属性,还必须指明是只读的还是可读可写的,用{ set get }来表示属性是可读可写的,只读属性则用{ get }来表示
代码语言:javascript
复制
protocol ClassAProtocol {
    var str: String {get set} // 继承他的时候不一定非要是计算型属性
    var str1: String {get} // 只读
    
    func log() -> String
}

class ClassA: ClassAProtocol {
    var str = "000"
    var str1 = "111"
    
    func log() -> String {
        return str
    }
}

var a: ClassA = ClassA()
print(a.log())

var ap: ClassAProtocol = a  //ClassAProtocol类型可以存放其子类

a.str = "666" // 不报错,因为a是可读可写的
ap.str1 = "888" // 报错,a因为a不可读

Mutating 方法要求

  • 在协议中定义了一个属性,该方法会改变遵循该协议的类型的实例,那么在定义协议时需要在方法前加 mutating 关键字
  • 实现协议中的 mutating 方法时,若是类类型,则不用写 mutating 关键字。而对于结构体和枚举,则必须写 mutating 关键字
代码语言:javascript
复制
protocol ClassAProtocol{
    var str:String{get set}
}
struct ClassA:ClassAProtocol{
    var str: String = "000"
    mutating func change(value:String) {
        str = value
    }
}
let a = ClassA.init()
a.str

对构造器要求

  • 可以在遵循该协议的类中实现构造器,并指定其为类的指定构造器或者便利构造器。在这两种情况下,你都必须给构造器实现标上required修饰符
代码语言:javascript
复制
protocol ClassAProtocol{
    init(a:Int)
}

class ClassA:ClassAProtocol{
    required init(a: Int) {
        print(a)
    }
}

let a = ClassA.init(a: 3)
  • 如果一个子类重写了父类的指定构造器,并且该构造器满足了某个协议的要求,那么该构造器的实现需要同时标注 required 和 override 修饰符
代码语言:javascript
复制
protocol ClassAProtocol{
    init()
}

class ClassA{
    init() {
        
    }
}

class ClassB:ClassA,ClassAProtocol{
    
    // 因为遵循协议,需要加上 required
    // 因为继承自父类,需要加上 override
    required override init() {
        
    }
}

协议作为类型

  • 协议本身并不实现任何功能,但是协议可以被当做类型来使用
  • 协议是一种类型,与其他类型(例如 Int,Double,String)的写法相同,使用大写字母开头的驼峰式写法
  • 使用场景
    • 作为函数、方法或构造器中的参数类型或返回值类型
    • 作为常量、变量或属性的类型
    • 作为数组、字典或其他容器中的元素类型
代码语言:javascript
复制
protocol ClassProtocol {
    func log() -> String
}

class ClassA:ClassProtocol{
    func log() -> String {
        return "classA"
    }
}

class ClassB:ClassProtocol{
    func log() -> String {
        return "classB"
    }
}

struct ClassC{
    var pro:ClassProtocol  //协议作为属性
    func run() -> String {
        return self.pro.log()
    }
}
let c = ClassC.init(pro: ClassA())
c.run()     //classA

代理模式

代码语言:javascript
复制
protocol DosomethingProtocol {
    func buy()
    func share()
}

import UIKit
class APP: NSObject,DosomethingProtocol {

    func buy() {
        print("buy")
    }
    func share() {
        print("share")
    }
}
---------------------
import UIKit

class Student: NSObject {

    var delegate:DosomethingProtocol?
}
-----------------------
let stu = Student()
let app = APP()
stu.delegate = app
stu.delegate!.share()

通过分类为现有类型添加属性、方法等等

代码语言:javascript
复制
protocol DosomethingProtocol {
    func buy()
    func share()
}
extension APP:DosomethingProtocol{
    func buy() {
        print("buy")
    }
    func share() {
        print("share")
    }
}
import UIKit
class APP: NSObject {
    var name:String?
    func study() {
        print("study")
    }
}

协议的继承

代码语言:javascript
复制
protocol DosomethingProtocol {
    func buy()
    func share()
}

protocol PlayProtocol:DosomethingProtocol {
    func play()
}

extension APP:PlayProtocol{
    func buy() {
        print("buy")
    }
    func share() {
        print("share")
    }
    func play() {
        print("Play")
    }
}
import UIKit
class APP: NSObject {
    var name:String?
    func study() {
        print("study")
    }
}


let app = APP.init()
app.name = "app"
app.study()
app.share()
app.buy()
app.play()

类类型专属协议

在协议的继承列表中,通过添加 class 关键字来限制协议只能被类类型遵循,而结构体或枚举不能遵循该协议。class 关键字必须第一个出现在协议的继承列表中,在其他继承的协议之前

类型专属协议.png

协议合成

需要同时遵循多个协议,可以将多个协议采用 Protocol & Protocol 这样的格式进行组合,称为 协议合成

代码语言:javascript
复制
protocol PlayProtocol{
    func playGame()
}
protocol StudyProtocol {
    func study()
}

class Boy:PlayProtocol,StudyProtocol{
    func playGame() {
        print("play")
    }
    func study() {
        print("study")
    }
    
    func log(info:PlayProtocol&StudyProtocol) {
        self.playGame()
        self.study()
    }
}

let boy = Boy()
boy.log(info: boy)

//play
//study

检查协议一致性

  • is 用来检查实例是否符合某个协议,若符合则返回 true,否则返回 false。
  • as? 返回一个可选值,当实例符合某个协议时,返回类型为协议类型的可选值,否则返回 nil。
  • as! 将实例强制向下转换到某个协议类型,如果强转失败,会引发运行时错误
代码语言:javascript
复制
protocol PlayProtocol{
    func playGame()
}

class Stu1:PlayProtocol{
    func playGame() {
        print("play")
    }}

class Stu2:PlayProtocol{
    func playGame() {
        print("play")
    }
}

class Stu3{
    
}

let stu1 = Stu1()
let stu2 = Stu2()
let stu3 = Stu3()

stu1 is PlayProtocol    //true
stu2 is PlayProtocol   //true
stu3 is PlayProtocol

stu1 as? PlayProtocol  //true
stu2 as? PlayProtocol  //true
stu3 as? PlayProtocol  //nil

可选协议

  • 协议和可选要求都必须带上@objc属性
  • 在协议中使用optional关键字作为前缀来定义可选要求
代码语言:javascript
复制
@objc protocol PlayProtocol{
    func playGame()
    @objc optional func run()
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 协议规定了用来实现某一特定功能所必需的方法和属性
  • 协议语法
  • 对属性、方法的规定
  • Mutating 方法要求
  • 对构造器要求
  • 协议作为类型
  • 代理模式
  • 通过分类为现有类型添加属性、方法等等
  • 协议的继承
  • 类类型专属协议
  • 协议合成
  • 检查协议一致性
  • 可选协议
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档