Swift学习笔记十六:协议

Protocol(协议)用于统一方法和属性的名称,而不实现不论什么功能。

协议可以被类。枚举。结构体实现。满足协议要求的类,枚举,结构体被称为协议的遵循者。

遵循者须要提供协议指定的成员,如属性,方法,操作符,下标等。



一、协议的基本的语法

咱们还是先上代码吧

protocol Human {
var name:String{ get set }
var isMan:Bool{set get}
class var isUsable:Bool { set get } //类成员。表示这个类是否可用
func ageDescription(ages:Int...) //函数參数能够是变长參数
}
class Student{
var name = ""
}
class PrimaryStudent:Student,Human{
class var isUsable:Bool{
get{ return self.isUsable }
set{ self.isUsable = newValue }
}
var isMan:Bool
init(name:String,isMan:Bool){
self.isMan = isMan
super.init()
self.name = name
}
func ageDescription(ages:Int...){
var ageCount = 0
for age in ages{
ageCount += age;
}
println("this man age is \(ageCount)")
}
}

重点:

     ① 遵守某个协议须要像继承一样。在:后面加入这个协议

     ② 假设既要继承又要遵守协议,须要把继承的父类放在最前面

     ③ 对于协议中的属性,须要标明属性的读写类型,能够是读写或者仅仅读(不能仅仅写不读)

     ④ 对于类成员,须要在协议中的属性前面加classkeyword,假设是类遵守协议加classkeyword,假设是枚举或者结构体遵守协议加statickeyword

     ⑤ 协议中方法支持变长參数,但不支持參数默认值



二、协议类型

     虽然协议本身并不实现不论什么功能,可是协议能够被当做类型来使用。

使用场景:

协议类型作为函数、方法或构造器中的參数类型或返回值类型

协议类型作为常量、变量或属性的类型

协议类型作为数组、字典或其它容器中的元素类型

protocol RandomNumberGenerator {
func random() -> Double
}
class Dice {
let sides: Int
let generator: RandomNumberGenerator
init(sides: Int, generator: RandomNumberGenerator) {
self.sides = sides
self.generator = generator
}
func roll() -> Int {
return Int(generator.random() * Double(sides)) + 1
}
} class LinearCongruentialGenerator: RandomNumberGenerator {
func random() -> Double {
return random()%10.0
}
}
var d6 = Dice(sides: 6,generator: LinearCongruentialGenerator())

解释:

     在Dice中。generator是RandomNumberGenerator协议类型。

所以仅仅能使用遵守RandomNumberGenerator协议的类、结构体、枚举类型给他赋值。在后面我们能够看到,在初始化的时候使用遵守RandomNumberGenerator协议的LinearCongruentialGenerator给他赋值了



三、托付代理模式

     玩过Objective-C的朋友相比对托付代理非常熟悉了,Swift中的托付代理和OC的大同小异,我们还是来看看代码吧

protocol NameComplete {
func nameSetCompleted(theName:String)
}
class Student{
var delegate:NameComplete?
var name:String{
didSet{
self.delegate?.nameSetCompleted(name)
}
}
init(name:String,delegate:NameComplete){
self.name = name
self.delegate = delegate
} }
class DoSth:NameComplete{
func nameSetCompleted(theName:String){
println("name:\(theName) is set ")
}
}
var a = DoSth()
var b = Student(name:"",delegate:a)
b.name = "小笨狼" //输出:name:小笨狼 is set

解释:

     NameComplete是一个代理。DoSth遵从并实现这个代理,Student调用代理。

在Student中name被赋值之后,代理中nameSetCompleted方法会被调用

     

三、可选协议

     玩过OC的朋友知道。OC中协议有的方法是可选的。在Swift中协议也有这个功能,以下我们来看看

@objc protocol Human{
@optional var name:String{get set}
@optional func descript()
}
class Student:Human{
var name:String = "abc"
func descript(){
println("abc")
}
}

重点:

     ① 对于可选方法或者属性。须要在方法或者属性前加上@optionalkeyword

     ② 假设协议中含有可选方法或者属性,在定义协议时须要在protocol 前加上@objckeyword

     ③ 在可选协议中,不能出现OC没有的类型。比方变长类型

     ④ 可选协议仅仅能被类遵从



四、协议继承

     协议和类一样。也能够继承

protocol pName{
var name:String{set get}
}
protocol dName:pName{
func descript()
}
class Human:dName{
var name = ""
func descript(){
println(name)
}
}

解释:

     dName继承了pName,所以dName协议不仅含有一个descript方法还含有name属性,所以遵从dName协议的类必须有name属性和descript方法



五、协议合成

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>) {
println("Happy birthday \(celebrator.name) - you're \(celebrator.age)!")
}
let birthdayPerson = Person(name: "Malcolm", age: 21)
wishHappyBirthday(birthdayPerson) //输出Happy birthday Malcolm - you're 21!

解释:

     wishHappyBirthday方法传入的參数是<Named, Aged>合成协议类型,这时能够传入遵从这2个协议的结构体的实例

     注意:

          协议合成并非生成一个新协议。而是多个协议合成一个暂时协议,超出范围后就会失效

上一篇:Swift学习笔记十四:构造(Initialization)


下一篇:Swift 学习笔记(四)