协议(Protocol)
一、定义
用于定义完成某项任务或功能所必须的方法和属性,协议实际上并不提供这些功能或任务的具体 实现
(Implementation) --而只用来描述这些实现应该是什么样的。类,结构体,枚举通过提供协议所要求的方法,属性的具体实现来 采用(adopt) 协议。任意能够满足协议要求的类型被称为协议的 遵循者 。
协议可以要求其遵循者提供特定的实例属性,实例方法,类方法,下标脚本,操作符等。
简单来讲:协议就是告诉编译器,这个类实现了这些属性和方法,可以进行调用。告诉用户,解决这一类问题,需要定义这些属性,实现这些方法。
二、语法
定义一个协议
采用一个协议
协议可以规定其属性提供特定名称特定类型的属性(类属性和实例属性均可),同时可以指定其读写全权限。采用协议的类,对应提供的属性的读写权限应该和协议一致。
协议中用{get set}表示读写,用{get}表示只读
举例
五、mutating方法的规定
简单说下mutating方法:对于结构体和枚举,由于是值类型,所以方法不能直接修改属性的值。但是加上mutating关键词之后,就可以修改。
注意:类实现mutating方法时候,不需要该关键字,因为类本身就可以修改。但是枚举和结构体需要。
举例:
//协议用来切换状态
协议要求遵循某协议的类型实现特定的构造器。
协议本身不实现任何事情,但是协议可以当做类型来使用。
几种情形:
1.协议作为函数的参数或者返回值
2.作为常量、变量或者属性的类型
3.作为数组、字典或者其他容器的类型
例如
使用的时候
比如你有一个类,你需要实现一个抽象解决方案,但是具体这个方法的实现并不知道,这时候就可以把这个抽象方法作为协议类型的参数保存起来,
等到用户实现这个类的时候,指明由那个协议的遵循着来实现这个方法。
协议在IOS开发中,绝大部分情况下还是用于Delegate和DataSource,会在下一篇进行讲解。
一、定义
用于定义完成某项任务或功能所必须的方法和属性,协议实际上并不提供这些功能或任务的具体 实现
(Implementation) --而只用来描述这些实现应该是什么样的。类,结构体,枚举通过提供协议所要求的方法,属性的具体实现来 采用(adopt) 协议。任意能够满足协议要求的类型被称为协议的 遵循者 。
协议可以要求其遵循者提供特定的实例属性,实例方法,类方法,下标脚本,操作符等。
简单来讲:协议就是告诉编译器,这个类实现了这些属性和方法,可以进行调用。告诉用户,解决这一类问题,需要定义这些属性,实现这些方法。
二、语法
定义一个协议
protocol SomeProtocal{
}
采用一个协议
class hwcClass:SomeProtocal{
}
同时具有继承关系和遵循一个协议
class hwcSubClass:hwcSuperClass,FirstProtocal,SecondProtocal{
}
三、协议对属性的规定
协议可以规定其属性提供特定名称特定类型的属性(类属性和实例属性均可),同时可以指定其读写全权限。采用协议的类,对应提供的属性的读写权限应该和协议一致。
协议中用{get set}表示读写,用{get}表示只读
举例
<pre name="code" class="plain">enum HwcDeviceState{
case One
case Off
case Unknown
}
protocol DeviceStateProtocol{
var state:HwcDeviceState{get set}
}
class BlueTooth:DeviceStateProtocol{
var state:HwcDeviceState //提供协议需要提供的属性
init(state:HwcDeviceState){
self.state = state
}
}
class Wifi:DeviceStateProtocol{
var state:HwcDeviceState //提供协议需要提供的属性
init(state:HwcDeviceState){
self.state = state
}
}
备注:这里有同学会问,那我为什么不干脆自己定义这个东西?以上述为例,我定义好了一个DeviceStateProtocol协议,那么你只要知道,所有涉及到Device的时候,遵循这个协议即可,编译器会提示你,遵循这个协议你应该实现什么东西,上述类中就是device的实例必须要提供给用户一个state查看当前设备的状态。也就是定义了解决一类问题的方法。
四、对方法的规定协议可以要求遵循者实现某些指定的方法,这些方法包括类方法和实例方法。
注意:协议中的方法不支持参数默协议中类方法用class关键词声明,结构体全局方法用static关键词声明举例:定义一个协议,协议要求实现方法来打印出实例的描述信息
protocol DescriptionProtocol{
func printDescription()
}
class NameClass:DescriptionProtocol{
var name:String?
func printDescription(){
println(name)
}
}
class CarClass:DescriptionProtocol{
var ID:String?
func printDescription(){
println(ID)
}
}
这里看到了,Name类和Car类都可以实现这个协议来打印出描述信息,这也就体现出了协议和继承的区别:协议解决的是提供解决一类抽象问题的解决方案,但是实现由具体的类决定,这些类之间可以毫无关系,只要他们都涉及到了这个抽象的解决方案。
五、mutating方法的规定
简单说下mutating方法:对于结构体和枚举,由于是值类型,所以方法不能直接修改属性的值。但是加上mutating关键词之后,就可以修改。
注意:类实现mutating方法时候,不需要该关键字,因为类本身就可以修改。但是枚举和结构体需要。
举例:
//协议用来切换状态
protocol Togglable {
mutating func toggle()
}
//遵循该协议
enum OnOffSwitch: Togglable {
case Off, On
mutating func toggle() {
switch self {
case Off:
self = On
case On:
self = Off
}
}
}
var lightSwitch = OnOffSwitch.Off
lightSwitch.toggle()
六、对构造器的规定
协议要求遵循某协议的类型实现特定的构造器。
protocol SomeProtocol {
init(someParameter: Int)
}
遵循该协议后,实现的对应构造器必须加上required关键字,required关键字保证一旦有类继承实现对应协议的类,那么子类也要提供相应的构造器。如果类不能为继承(用final修饰),则不需要该关键字
class SomeClass: SomeProtocol {
required init(someParameter: Int) {
//构造器实现
}
}
七、协议类型
协议本身不实现任何事情,但是协议可以当做类型来使用。
几种情形:
1.协议作为函数的参数或者返回值
2.作为常量、变量或者属性的类型
3.作为数组、字典或者其他容器的类型
例如
protocol DescriptionProtocol{
func printDescription()
}
class NameClass:DescriptionProtocol{
var name:String
func printDescription(){
println(name)
}
init(name:String){
self.name = name
}
}
class CarClass:DescriptionProtocol{
var ID:String
func printDescription(){
println(ID)
}
init(id:String){
self.ID = id
}
}
class HwcTestClass{
var hwcDescription:DescriptionProtocol
init(desc:DescriptionProtocol){
self.hwcDescription = desc
}
func print(){
hwcDescription.printDescription()
}
}
使用的时候
var carInstance = HwcTestClass(desc:CarClass(id:"as1234"))
carInstance.print()
是不是和以父类指针为参数,传入子类指针相似呢?
比如你有一个类,你需要实现一个抽象解决方案,但是具体这个方法的实现并不知道,这时候就可以把这个抽象方法作为协议类型的参数保存起来,
等到用户实现这个类的时候,指明由那个协议的遵循着来实现这个方法。
协议在IOS开发中,绝大部分情况下还是用于Delegate和DataSource,会在下一篇进行讲解。