Swift之协议(protocol)
2022-06-16 本文已影响0人
小羊爱学习
协议(protocol)规定了用来实现某一特定功能所必需的方法和属性。
任意能够满足协议要求的类型被称为遵循(conform)这个协议。
类,结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能。
语法
protocol SomeProtocol {
// 协议内容
}
要使类遵循某个协议,需要在类型名称后加上协议名称,中间以冒号:分隔,作为类型定义的一部分。遵循多个协议时,各协议之间用逗号,分隔。
struct SomeStructure: FirstProtocol, AnotherProtocol {
// 结构体内容
}
如果类在遵循协议的同时拥有父类,应该将父类名放在协议名之前,以逗号分隔。
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
// 类的内容
}
对属性的规定
协议用于指定特定的实例属性或类属性,而不用指定是存储型属性或计算型属性。此外还必须指明是只读的还是可读可写的。
协议中的通常用var来声明变量属性,在类型声明后加上{ set get }来表示属性是可读可写的,只读属性则用{ get }来表示。
@objc protocol classa {
var marks: Int { get set }
var result: Bool { get }
func attendance() -> String
@objc optional func markssecured() -> String
}
protocol classb: classa {
var present: Bool { get set }
var subject: String { get set }
var stname: String { get set }
init(aprot: Int)
}
class LearnProtocol: classb {
//自有的
var aprot:Int?
//遵守协议拥有的
func attendance() -> String {
return "attendance"
}
//optional
// func markssecured() -> String {
// return "markssecured"
// }
var marks: Int = 96
var result: Bool = true
var present: Bool = false
var subject: String = "match"
var stname: String = "xiaoming"
//你可以在遵循该协议的类中实现构造器,并指定其为类的指定构造器或者便利构造器。在这两种情况下,你都必须给构造器实现标上"required"修饰符:
required init(aprot: Int) {//
self.aprot = aprot
}
}
required
使用required修饰符可以保证:所有的遵循该协议的子类,同样能为构造器规定提供一个显式的实现或继承实现。
如果一个子类重写了父类的指定构造器,并且该构造器遵循了某个协议的规定,那么该构造器的实现需要被同时标示required和override修饰符:
protocol tcpprotocol {
init(no1: Int)
}
class mainClass {
var no1: Int // 局部变量
init(no1: Int) {
self.no1 = no1 // 初始化
}
}
class subClass: mainClass, tcpprotocol {
var no2: Int
init(no1: Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// 因为遵循协议,需要加上"required"; 因为继承自父类,需要加上"override"
required override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
注意和上述例子不同的地方,此例子是在父类中遵循了协议
protocol ceshiProtocol {
func getname()
init(no:Int)
init()
}
class ceshiClass: ceshiProtocol {
func getname() {
print("getname")
}
required init(no: Int) {
}
required init() {
}
//自有的
init (no3: Int){
}
required init (no4: Int){
}
}
//此时的ceshiSubjectClass子类只需要考虑继承关系即可,因为父类遵循的协议 必定在父类中实现协议方法,而子类继承自父类,也就自带了这些协议方法,如果再单独实现父类尊旭的协议方法,也就属于重写了 需要override
class ceshiSubjectClass: ceshiClass{
// override func getname() {
// print("ceshiSubjectClass - getname")
// }
//
required init(no: Int) {//可以看出 父类如果有了require修饰构造方法,则子类可以不用override修饰
super.init(no: no)
}
required init() {
super.init()
}
override init(no3: Int) {//单纯的继承init,则是override
super.init(no3: no3)
}
required init(no4: Int) {//require修饰的init 则需要require
super.init(no4: no4)
}
}
检验协议的一致性
你可以使用is和as操作符来检查是否遵循某一协议或强制转化为某一类型。
is操作符用来检查实例是否遵循了某个协议。
as?返回一个可选值,当实例遵循协议时,返回该协议类型;否则返回nil。
as用以强制向下转型,如果强转失败,会引起运行时错误。
协议的扩展
protocol clubProtocol {
func getname()
func getChild() -> Bool
}
class studentName: clubProtocol{
func getname() {
print("getname")
}
}
extension clubProtocol {
func getChild() -> Bool {
return false;//扩展默认为false,这样student就可以不用实现getchild方法了
}
}
//optional 属于objc中的协议中的成员关键字,因此这里如果不用协议扩展,可用objc中的optional修饰,但这就没有了协议扩展中的默认实现了
@objc protocol clubProtocolTwo {
@objc optional func getmoney()
}
class studentMoney: clubProtocolTwo {
}
类扩展可以使其遵循协议,如果类本身已经有了协议的内容,则在扩展中可以不用写
protocol CharityProtocol {
var donateMoney: Float {get}
func activity(str: String)
static func driving() -> Void
init(clubLabel: String)
func hasChildren() -> Bool
}
extension CharityProtocol {
func hasChildren() -> Bool {
return false
}
}
class defauleMan {
private var name: String?
func activity(str: String) {
print(str)
}
required init(clubLabel: String) {
print(clubLabel)
}
}
extension defauleMan: CharityProtocol {//activity和init 本身类中已经实现了
var donateMoney: Float {//扩展不能扩展存储属性,因此这里要用计算属性
return 32
}
static func driving() {
print("driving")
}
}
协议的继承,可以为一个完整的协议,再次追加条件
protocol newCharityProtocol: CharityProtocol {
var newDonateMoney: Float {get}
}
协议作为类型使用
可用于参数类型/返回类型;变量/常量/属性;集合类型中的元素类型
class newClub {
private var members = [newCharityProtocol]()
func addMember(man: newCharityProtocol) {
self.members.append(man)
}
}