首页 > 代码库 > Swift学习笔记十六:协议
Swift学习笔记十六:协议
Protocol(协议)用于统一方法和属性的名称,而不实现任何功能。协议能够被类,枚举,结构体实现,满足协议要求的类,枚举,结构体被称为协议的遵循者。
遵循者需要提供协议指定的成员,如属性,方法,操作符,下标等。
一、协议的基本语法
重点:
① 遵守某个协议需要像继承一样,在:后面添加这个协议
② 如果既要继承又要遵守协议,需要把继承的父类放在最前面
③ 对于协议中的属性,需要标明属性的读写类型,可以是读写或者只读(不能只写不读)
④ 对于类成员,需要在协议中的属性前面加class关键字,如果是类遵守协议加class关键字,如果是枚举或者结构体遵守协议加static关键字
⑤ 协议中方法支持变长参数,但不支持参数默认值
二、协议类型
尽管协议本身并不实现任何功能,但是协议可以被当做类型来使用。
使用场景:
协议类型作为函数、方法或构造器中的参数类型或返回值类型
协议类型作为常量、变量或属性的类型
协议类型作为数组、字典或其他容器中的元素类型
解释:
在Dice中,generator是RandomNumberGenerator协议类型。所以只能使用遵守RandomNumberGenerator协议的类、结构体、枚举类型给他赋值。在后面我们可以看到,在初始化的时候使用遵守RandomNumberGenerator协议的LinearCongruentialGenerator给他赋值了
三、委托代理模式
玩过Objective-C的朋友相比对委托代理很熟悉了,Swift中的委托代理和OC的大同小异,我们还是来看看代码吧
解释:
NameComplete是一个代理,DoSth遵从并实现这个代理,Student调用代理。在Student中name被赋值之后,代理中nameSetCompleted方法会被调用
三、可选协议
玩过OC的朋友知道,OC中协议有的方法是可选的。在Swift中协议也有这个功能,下面我们来看看
重点:
① 对于可选方法或者属性,需要在方法或者属性前加上@optional关键字
② 如果协议中含有可选方法或者属性,在定义协议时需要在protocol 前加上@objc关键字
③ 在可选协议中,不能出现OC没有的类型,比如变长类型
④ 可选协议只能被类遵从
四、协议继承
协议和类一样,也可以继承
解释:
dName继承了pName,所以dName协议不仅含有一个descript方法还含有name属性,所以遵从dName协议的类必须有name属性和descript方法
五、协议合成
解释:
wishHappyBirthday方法传入的参数是<Named, Aged>合成协议类型,这时可以传入遵从这2个协议的结构体的实例
注意:
协议合成并不是生成一个新协议,而是多个协议合成一个临时协议,超出范围后就会失效
遵循者需要提供协议指定的成员,如属性,方法,操作符,下标等。
一、协议的基本语法
咱们还是先上代码吧
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)") } }
重点:
① 遵守某个协议需要像继承一样,在:后面添加这个协议
② 如果既要继承又要遵守协议,需要把继承的父类放在最前面
③ 对于协议中的属性,需要标明属性的读写类型,可以是读写或者只读(不能只写不读)
④ 对于类成员,需要在协议中的属性前面加class关键字,如果是类遵守协议加class关键字,如果是枚举或者结构体遵守协议加static关键字
⑤ 协议中方法支持变长参数,但不支持参数默认值
二、协议类型
尽管协议本身并不实现任何功能,但是协议可以被当做类型来使用。
使用场景:
协议类型作为函数、方法或构造器中的参数类型或返回值类型
协议类型作为常量、变量或属性的类型
协议类型作为数组、字典或其他容器中的元素类型
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") } }
重点:
① 对于可选方法或者属性,需要在方法或者属性前加上@optional关键字
② 如果协议中含有可选方法或者属性,在定义协议时需要在protocol 前加上@objc关键字
③ 在可选协议中,不能出现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个协议的结构体的实例
注意:
协议合成并不是生成一个新协议,而是多个协议合成一个临时协议,超出范围后就会失效
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。