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)
    }
    
}
上一篇下一篇

猜你喜欢

热点阅读