协议定义了一个蓝图,规定了用来实现某一特定工作或者功能所必须的方法和属性。类、结构体或者枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能。任意能满足协议要求的类型被称为遵循conform这个协议。

  除了遵循协议的类型必须实现那些指定的规定以外,还可以对协议进行扩展,实现一些特殊的规定或者一些附加的功能,使得遵循的类型能够受益。

  协议的公式:

protocol SomeProtocol { // 协议内容
}

  要使类遵循某个协议,需要在类型名称后加上协议名称,中间以冒号:分隔,作为类型定义的一部分,遵循多个协议时,各协议之间用逗号,分隔。

struct SomeStructure:FirstProtocol,AnotherProtocol{
//结构体内容
}

  如果类在遵循协议的同时拥有父类,应该将父类名放在协议名之前,以逗号分隔。

class SomeClass:SomeSuperClass,FirstProtocol,AnotherProtocol{
//类的内容
}

  ****对属性的规定

  协议可以规定其 遵循者提供特定名称和类型的实例属性(instance property)或类属性(type property),而不用指定是存储型属性(stored property)还是计算型属性(calculate property),此外还必须指明是可读的还是可读可写的。

  如果协议规定属性是可读可写的,那么这个属性不能是常量或只读的计算属性。如果协议只要求属性是只读的(gettable),那么属性不仅可以是只读的,如果你代码需要的话,也可以是可写的。

  协议中的通常用var来声明变量属性,在类型声明后加上{set get}来表示属性是可读可写的,只读属性则用{get}来表示。

protocol SomeProtocol{
var mustBeSettable:Int {get set}//可读可写
var doneNotNeedToBeSettable:Int{get} //只读
}

  在协议中定义类属性(type property)时,总是使用static 关键字作为前缀。当协议的遵循者是类时,可以使用class 或static关键字来声明类属性。

protocol AnotherProtocol{
static var someTypeProperty:Int{get set}
}

  例子来了····

protocol FullyNamed{
var fullName:String {get}
}

  FullyNamed协议除了要求协议的遵循者提供全名属性外,对协议对遵循者的类型并没有特别的要求。这个协议表示,任何遵循FullyNamed协议的类型,都具有一个可读的String类型实例属性fullyName。

//一个遵循FullNamed协议的简单结构体
struct Person:FullyNamed{
var fullName:String
}
let john = Person(fullName:"John Appleseed")

  这个例子定义了一个叫做Person的结构体,用来表示具有名字的人,从第一行代码中可以看出,它遵循了FullyNamed协议。

  Person结构体的每一个实例都有一个String类型的存储型属性fullName。这正好满足了FullyNamed协议的要求,也就意味着,Person结构体完整地遵循了协议。---如果协议要求未被完全满足,在编译时会报错

class Starship:FullyNamed{
var prefix:String?
var name:String
init(name:String, prefix:String? = nil){
self.name = name
self.prefix = prefix
}
var fullName:String{
return (prefix != nil ? prefix! + "":"")+name
}
}
var ncc = Starship(name:"Enterprise", prefix:"USS")

  将fullName属性实现为可读的计算型属性。

  ******对方法的规定

  协议可以要求其遵循者实现某些指定的实例方法或类方法。这些方法作为协议的一部分,像普通的方法一样放在协议的定义中,但是不需要大括号和方法体。可以在协议中定义具有可变参数的方法,和普通的方法定义方式相同。但是在协议的方法定义中,不支持参数默认值。

  正如对属性的规定中所说的,在协议中定义类方法的时候,总是使用static关键字作为前缀。当协议的遵循者是类的时候,你可以在类的实现中使用class或者static来定义类方法:

protocol SomeProtocol{
static func someTypeMethod()
}

  下面的例子定义了含有一个实例方法的协议:

protocol RandomNumberGenerator{
func random() -> Double
}

  ******对Mutating方法的规定

  有时需要在方法中改变它的示例。eg:值类型(结构体、枚举)的实例方法中,将mutating关键字作为函数的前缀,写在func之前,表示可以在该方法中修改它所属的实例及其实例属性的值。

  ------用类实现协议中的mutating方法时,不用写mutating关键字;用结构体,枚举实现协议中的mutating方法时,必须写mutating关键字。

  *******对构造器的规定

  协议可以要求它的遵循者实现特定的构造器,可以在协议的定义里写下构造器的声明,但是不需要写花括号和构造器的实体。

protocol SomeProtocol{
init(someParameter:Int)
}

  协议构造器规定在类中的实现

  可以在遵循该协议的类中实现构造器,并指定其为类的指定构造器(designated initializer)或者便利构造器(convenience initializer).在这种情况下,你都必须给构造器标上"required"修饰符。

  

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

  使用required修饰符可以保证:所有的遵循该协议的子类,同样能为构造器规定提供一个显式的实现或者继承实现。

  如果类已经被标记为final,那么不需要在协议构造器的实现中使用required修饰符。因为final类不能有子类。

  如果一个子类重写了父类的指定构造器,并且该构造器遵循了某个协议的规定,那么该构造器的实现需要被同事标识required 和override修饰符:

  

protocol SomeProtocol{
init()
} class SomeSuperClass{
init(){
//构造器的实现
}
} class SomeSubClass:SomeSuperClass,SomeProtocol{
//因为遵循协议,需要加上required;因为继承自父类,需要加上override
required override init(){ }
}

  ****可失败构造器

  可以通过给协议Protocols中添加可失败构造器来使遵循该协议的类型必须实现该可失败构造器。

  如果在协议中定义一个可失败构造器,则在遵循该协议的类型中必须添加同名同参数的可失败构造器或非可失败构造器。如果在协议中定义一个非可失败构造器,则在遵循该协议的类型中必须添加同名同参数的非可失败构造器或隐式解析类型的可失败构造器(init!).

  *****协议类型

  尽管协议本身并不实现任何功能,但是协议可以被当做类型来使用。

  协议可以像其他普通类型一样使用,使用场景:
  1.作为函数、方法或者构造器中的参数类型或者返回值类型;

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

  3.作为数组、字典或者其他容器中的元素类型。

  Attention:

  协议是一种类型,因此协议类型的名称应与其他类型(Int ,Double,String)的写法相同,使用大写字母开头的驼峰式写法。

  

Swift-11-协议(Protocols)的更多相关文章

  1. Swift泛型协议的N种用法

    They said "you should learn a new language every year," so I  learned Swift. Now  I  learn ...

  2. 802.11协议帧格式、Wi-Fi连接交互过程、无线破解入门研究

    相关学习资料 Linux黑客大曝光: 第8章 无线网络 无线网络安全攻防实战进阶 无线网络安全 黑客大曝光 第2版 http://zh.wikipedia.org/wiki/IEEE_802.11 h ...

  3. WIFI:802.11协议帧格式

    802协议桢格式 802.11和Wi-Fi技术并不是同一个东西.Wi-Fi标准是802.11标准的一个子集,并且是Wi-Fi联盟负责管理 802协议桢格式: 协议 发布年份/日期 Op.标准频宽 实际 ...

  4. Welcome-to-Swift-21协议(Protocols)

    协议定义了一个方法的蓝图,属性和其他适合特定任务或功能的要求.协议实际上并不提供一个这些要求的实现,它只是描述了一个实现会是什么样子.协议可以通过一个类,结构或枚举提供这些要求的具体实现.满足要求的任 ...

  5. Swift学习——A Swift Tour 协议和扩展

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/zhenyu5211314/article/details/28854395 Protocols an ...

  6. 窥探Swift之协议(Protocol)和委托代理(Delegate)回调的使用

    协议与委托代理回调在之前的博客中也是经常提到和用到的在<Objective-C中的委托(代理)模式>和<iOS开发之窥探UICollectionViewController(四) - ...

  7. Swift利用协议优化NSNotificationCenter

    NSNotificationCenter存在的问题 通知没有统一的命名格式 对于通知的命名没有强制的要求,一个项目里可能有多种不同的命名规则.比如: 1 2 3 4 5 6 class Barista ...

  8. swift 当协议遇见了泛型

    由于泛型比较简单,并没有单独拿出来介绍!我们在定义函数的时候,有时候只是由于参数或者返回值类型不同,而具体的实现过程是一模一样的,这个时候我们就可以定义泛型函数而使可以传入不同的参数类型: func ...

  9. 利用Swift之协议语法实现页面间的传值功能

    随着Swift 新开发语言的发布,又随着Xcode6.0.1的正式发布,利用swift编写iOS代码迫在眉睫,笔者在使用Objective-C开发近三年以来,对这种优雅的语法深感赞叹,下面我将对比式的 ...

  10. swift 用协议实现代理传值功能

    1.功能简介 RootViewController中用个lable和一个按钮,点击按钮跳转到模态窗口.在模态窗口中有个TextField和一个按钮,输入文字点击关闭模态按钮后跳转到RootViewCo ...

随机推荐

  1. CentOS 多网卡绑定bonding

    1.查看环境 ip a |grep -v lo 2.加载bonding模块 modprobe bonding 3.开机自动加载模块到内核 echo 'modprobe bonding &> ...

  2. HDU 2852 KiKi's K-Number(离线+树状数组)

    题目链接 省赛训练赛上一题,貌似不难啊.当初,没做出.离线+树状数组+二分. #include <cstdio> #include <cstring> #include < ...

  3. 原创Java版的Shell

    如果你接触过windows操作系统,你应该对windows中的cmd有一定的了解. 如果你接触过Linux操作系统,你应该对Linux的shell有一定的了解. 本文说的正是linux中的shell. ...

  4. (转载)读取xml中的指定节点的值

            /// <summary>         /// 读取xml中的指定节点的值        /// </summary>         private st ...

  5. 李洪强-C语言9-C语言的数据,变量和常量

    一.数据 图片文字等都是数据,在计算机中以0和1存储. (一)分类 数据分为静态数据和动态数据. ①. 静态数据:一些永久性的的数据,一般存储在硬盘中,只要硬盘没坏数据都是存在的.一般以文件的形式存储 ...

  6. Matlab Delete Row or Col 删除矩阵的行或列

    Matlab中,我们有时候要删除矩阵中的某行某列,可以采用下列方法进行删除: a = [ ]; a(,:) = []; % Delete row a(:,) = []; % Delete col

  7. lightning mdb 源代码分析(1)

    lighting mdb(lmdb) 是一个高性能mmap kv数据库,基本介绍和文档参见symas官网,本文将尝试分析其源代码结构以理解数据库设计的关键技术. 本系列文章将尝试从以下几个方面进行分析 ...

  8. #在FLAT模式下,需要设置flat子网,VM的IP从这个设置的子网中抓取,这时flat_injected需要设置为True,系统才能自动获得IP,如果flat

    #在FLAT模式下,需要设置flat子网,VM的IP从这个设置的子网中抓取,这时flat_injected需要设置为True,系统才能自动获得IP,如果flat子网和主机网络是同一网络,网络管理员要注 ...

  9. div居中(内容+元素:水平+垂直)

    内容水平居中 text-align: center; 内容垂直居中 /*第一种 行内垂直居中*/ height: 43px; line-height:43px; /*我们将行距增加到和整个div一样高 ...

  10. cURL 学习笔记与总结(5)用 cURL 访问 HTTPS 资源

    <?php $curlobj = curl_init(); // 初始化 curl_setopt($curlobj, CURLOPT_URL, "https://ajax.aspnet ...