协议(Protocols)

协议:规定了用来实现某一特定 工作 或者 功能 所必须的 方法 和 属性。

类、结构体,枚举 都可以遵循协议。(协议要求类,结构体,枚举必须实现协议要求的 属性 和 方法。)

任意能够满足协议要求的类型被称为 遵循 这个协议。

协议除了遵守协议还可以进行协议扩展,来实现一些附加的特殊功能。

协议语法:

protocol SomeProtocol {
      // 协议内容
}

遵循某个协议
遵循某个协议,需要在类型名称后面加上协议名称,中间以冒号, 作为类型定义的一部分。

struct SomeStructure : FistProtocol , AnotherProtocol {
        // 结构体的内容( 属性 和 方法)
}

类在遵守协议的同时拥有父类,父类名放在协议的前面,以逗号进行分隔。

class SomeClass: SomeSuperClasses, FistProtocol , AnotherProtocol {
      // 类的内容
}

协议对属性的规定

协议可以规定其 遵守者 提供特定名称和类型的 实例属性(instance property) 或者 类属性(type property)

协议是不能指定 属性 是 **存储属性 ** 还是 ** 计算属性 **。
协议可以指定 属性可读的 还是 ** 可读可写的 **。

  1. 协议要求属性是可读可写的,那么属性不能是 常量属性只读的计算型属性
  1. 如果协议只 要求属性是可读的,那么这个属性 不仅 是可读的,可以通过代码修改为可读可写的。

  2. 协议总是用 var 关键字来声明 变量属性,在类型名称后加上 { set get } 来表示属性是可读可写的,用 { get } 来表示可读:

protocol SomeProtocol {
      var mustBeSettable: Int { get set }
      var doseNotNeedToBeSettable: Int  { get }
}
  1. 类型属性的定义: 协议中总是使用 ** static ** 关键字作为前缀。当类类型采纳协议时,除了 使用 static 关键字,还可以使用 class 关键字来声明类属性:
protocol AnotherProtocol {
        // 类型属性
        static var someTypeProperty: Int {  get set }
}
protocol FullNamed {
        // 实例属性
        var fullName: String { get }
}

协议对于方法的规定

协议要求采纳协议的类型实现某些指定的 实例方法类方法

  1. 可以在协议中定义具有可变参数的方法(和普通方法的定义一样)
  1. 不支持为协议中的方法的参数提供默认值

  2. 协议中定义方法,使用 static关键字作为前缀。 当类类型采纳协议时,除了 使用 static 关键字,还可以使用 class 关键字最为前缀

protocol SomeProtocol {
        // 类型方法
        static fun someTypeMethod()
      
        // 实例方法
        fun random() -> Double
}

Mutating 关键字的使用

Mutating 主要是用在值类型(结构体 和 枚举)实例方法中。
将 mutating 关键字作为方法的前缀,写在 func 关键字之前。表示 可以在该方法中修改他所属的实例以及实例的任意属性值

结构体 和 枚举 是值类型,默认情况下值类型的属性是不能再他的实例方法中进行修改。

在协议中定义实例方法的时候,当方法会改变采纳该协议的类型的实例的时候,在定义协议方法的时候需要在方法前加 mutating 关键字。(主要是给枚举和结构体准备的)

在协议中定义了实例方法,如果遵协议的类型是 枚举结构体,那么就需要在协议方法的前面添加 mutating 关键字。

构造器要求

协议可以要求采纳协议的类型实现指定的 构造器

protocol SomeProtocol {
        init(someParamer: Int)
}

构造器要求在类中的实现
采纳协议的类实现构造器,无论是指定构造器,还是便利构造器。都需要在构造器实现上 ** required ** 修饰符:

class SomeClass: SomeProtocol {
        required init(someParameter:Int){
                // 构造器实现  
      }
}

可选协议

在协议中使用 optional 关键字作为前缀来定义可选要求。

使用可选要求时,可选的方法或函数的类型会自动变为可选。
** 是整个函数的类型是可选的 **

协议合成
当需要同时采纳多个协议,我们可以使用协议合成。protocol <SomeProtocol, AnotherProtocol> 的格式进行组合。协议组合主要用在函数方法传参的地方。

protocol Named {
    var name: String { get }
}
protocol Aged {
    var age: Int { get }
}
struct Person: Named, Aged {
    var name: String
    var age: Int
}
func wishHappyBirthday(celebrator: protocol<Named, Aged>) {
    print("Happy birthday \(celebrator.name) - you're \(celebrator.age)!")
}
let birthdayPerson = Person(name: "Malcolm", age: 21)
wishHappyBirthday(birthdayPerson)
// 打印 “Happy birthday Malcolm - you're 21!”

协议扩展

协议可以通过 扩展 来为采纳协议的类型提供属性、方法以及下标的实现
你可以基于协议本身来实现这些功能, 而无需再每个采纳协议的类型中都重复同样实现。也无需使用全局函数。

extension RandomNumberGeneraator {
        func randomBool() -> Bool {
                return random() > 0.5 
        }
}

** 通过协议扩展,所有采纳协议的类型,都能自动获得这个扩展所增加的方法实现,无需任何修改。 **

let generator = LinearCongruentialGenerator()
print("Here's a random number: \(generator.random())")
// 打印 “Here's a random number: 0.37464991998171”
print("And here's a random Boolean: \(generator.randomBool())")
// 打印 “And here's a random Boolean: true”

** 提供默认实现 **
协议可以通过 扩展 来为采纳协议的类型提供属性、方法以及下标提供 默认 的实现

采纳协议的类型提供了自己的实现,那么自定义的实现将会替代扩展中的默认实现。

通过协议扩展为协议要求提供的默认实现和可选的协议要求不同:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容