美文网首页
Swift之协议(protocol)

Swift之协议(protocol)

作者: 小羊爱学习 | 来源:发表于2022-06-16 11:46 被阅读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)
        }
        
    }
    

    相关文章

      网友评论

          本文标题:Swift之协议(protocol)

          本文链接:https://www.haomeiwen.com/subject/qtxqvrtx.html