Swift - 协议

  • 简述

    协议为方法、属性和其他需求功能提供了蓝图。它只是被描述为方法或属性框架而不是实现。方法和属性的实现可以通过定义类、函数和枚举来进一步完成。协议的一致性被定义为满足协议要求的方法或属性。

    句法

    协议也遵循与类、结构和枚举类似的语法 -
    
    protocol SomeProtocol {
       // protocol definition 
    }
    
    协议在类、结构或枚举类型名称之后声明。单协议和多协议声明也是可能的。如果定义了多个协议,它们必须用逗号分隔。
    
    struct SomeStructure: Protocol1, Protocol2 {
       // structure definition 
    }
    
    当必须为超类定义协议时,协议名称应在超类名称之后使用逗号。
    
    class SomeClass: SomeSuperclass, Protocol1, Protocol2 {
       // class definition 
    }
    
  • 属性和方法要求

    协议用于指定特定的类类型属性或实例属性。它只是单独指定类型或实例属性,而不是指定它是存储属性还是计算属性。此外,它用于指定属性是“gettable”还是“settable”。
    属性要求由“var”关键字声明为属性变量。{get set} 用于在类型声明后声明 gettable 和 settable 属性。Gettable 在其类型声明之后由 {get} 属性提及。
    
    protocol classa {
       var marks: Int { get set }
       var result: Bool { get }
       
       func attendance() -> String
       func markssecured() -> String
    }
    protocol classb: classa {
       var present: Bool { get set }
       var subject: String { get set }
       var stname: String { get set }
    }
    class classc: classb {
       var marks = 96
       let result = true
       var present = false
       var subject = "Swift 4 Protocols"
       var stname = "Protocols"
       func attendance() -> String {
          return "The \(stname) has secured 99% attendance"
       }
       func markssecured() -> String {
          return "\(stname) has scored \(marks)"
       }
    }
    let studdet = classc()
    studdet.stname = "Swift 4"
    studdet.marks = 98
    studdet.markssecured()
    print(studdet.marks)
    print(studdet.result)
    print(studdet.present)
    print(studdet.subject)
    print(studdet.stname)
    
    当我们使用操场运行上述程序时,我们得到以下结果 -
    
    98
    true
    false
    Swift 4 Protocols
    Swift 4
    
  • 变异方法要求

    
    protocol daysofaweek {
       mutating func print()
    }
    enum days: daysofaweek {
       case sun, mon, tue, wed, thurs, fri, sat 
       mutating func print() {
          switch self {
             case sun:
                self = sun
                print("Sunday")
             case mon:
                self = mon
                print("Monday")
             case tue:
                self = tue
                print("Tuesday")
             case wed:
                self = wed
                print("Wednesday")
             case mon:
                self = thurs
                print("Thursday")
             case tue:
                self = fri
                print("Friday")
             case sat:
                self = sat
                print("Saturday")
             default:
                print("NO Such Day")
          }
       }
    }
    var res = days.wed
    res.print()
    
    当我们使用操场运行上述程序时,我们得到以下结果 -
    
    Wednesday
    
  • 初始化程序要求

    Swing 允许用户初始化协议以遵循类似于普通初始化程序的类型一致性。

    句法

    
    protocol SomeProtocol {
       init(someParameter: Int)
    }
    

    例如

    
    protocol tcpprotocol {
       init(aprot: Int)
    }
    
  • 协议初始值设定项要求的类实现

    指定或便利的初始化器允许用户通过保留的“必需”关键字初始化协议以符合其标准。
    
    class SomeClass: SomeProtocol {
       required init(someParameter: Int) {
          // initializer implementation statements
       }
    }
    protocol tcpprotocol {
       init(aprot: Int)
    }
    class tcpClass: tcpprotocol {
       required init(aprot: Int) {
       }
    }
    
    协议一致性在所有子类上通过“required”修饰符确保显式或继承实现。
    当子类覆盖其超类初始化要求时,它由“覆盖”修饰符关键字指定。
    
    protocol tcpprotocol {
       init(no1: Int)
    }
    class mainClass {
       var no1: Int        // local storage
       init(no1: Int) {
          self.no1 = no1  // initialization
       }
    }
    class subClass: mainClass, tcpprotocol {
       var no2: Int
       init(no1: Int, no2 : Int) {
          self.no2 = no2
          super.init(no1:no1)
       }
       // Requires only one parameter for convenient method
       required override convenience init(no1: Int) {
          self.init(no1:no1, no2:0)
       }
    }
    let res = mainClass(no1: 20)
    let print = subClass(no1: 30, no2: 50)
    print("res is: \(res.no1)")
    print("res is: \(print.no1)")
    print("res is: \(print.no2)")
    
    当我们使用操场运行上述程序时,我们得到以下结果 -
    
    res is: 20
    res is: 30
    res is: 50
    
  • 作为类型的协议

    它们不是在协议中实现功能,而是用作函数、类、方法等的类型。
    协议可以作为类型访问 -
    • 函数、方法或初始化为参数或返回类型
    • 常量、变量或属性
    • 数组、字典或其他容器作为项目
    
    protocol Generator {
       typealias members
       func next() -> members?
    }
    var items = [10,20,30].generate()
    while let x = items.next() {
       print(x)
    }
    for lists in map([1,2,3], {i in i*5}) {
       print(lists)
    }
    print([100,200,300])
    print(map([1,2,3], {i in i*10}))
    
    当我们使用操场运行上述程序时,我们得到以下结果 -
    
    10
    20
    30
    5
    10
    15
    [100, 200, 300]
    [10, 20, 30]
    
  • 使用扩展添加协议一致性

    通过使用扩展,可以采用现有类型并符合新协议。在扩展的帮助下,可以将新的属性、方法和下标添加到现有类型。
    
    protocol AgeClasificationProtocol {
       var age: Int { get }
       func agetype() -> String
    }
    class Person {
       let firstname: String
       let lastname: String
       var age: Int
       
       init(firstname: String, lastname: String) {
          self.firstname = firstname
          self.lastname = lastname
          self.age = 10
       }
    }
    extension Person : AgeClasificationProtocol {
       func fullname() -> String {
          var c: String
          c = firstname + " " + lastname
          return c
       }
       func agetype() -> String {
          switch age {
             case 0...2:
                return "Baby"
             case 2...12:
                return "Child"
             case 13...19:
                return "Teenager"
             case let x where x > 65:
                return "Elderly"
             default:
                return "Normal"
          }
       }
    }
    
  • 协议继承

    Swift 4 允许协议从其定义的属性中继承属性。它类似于类继承,但可以选择列出多个以逗号分隔的继承协议。
    
    protocol classa {
       var no1: Int { get set }
       func calc(sum: Int)
    }
    protocol result {
       func print(target: classa)
    }
    class student2: result {
       func print(target: classa) {
          target.calc(sum: 1)
       }
    }
    class classb: result {
       func print(target: classa) {
          target.calc(sum: 5)
       }
    }
    class student: classa {
       var no1: Int = 10
       
       func calc(sum: Int) {
          no1 -= sum
          print("Student attempted \(sum) times to pass")
             
          if no1 <= 0 {
             print("Student is absent for exam")
          }
       }
    }
    class Player {
       var stmark: result!
       init(stmark: result) {
          self.stmark = stmark
       }
       func print(target: classa) {
          stmark.print(target: target)
       }
    }
    var marks = Player(stmark: student2())
    var marksec = student()
    marks.print(target: marksec)
    marks.print(target: marksec)
    marks.print(target: marksec)
    marks.stmark = classb()
    marks.print(target: marksec)
    marks.print(target: marksec)
    marks.print(target: marksec)
    
    当我们使用操场运行上述程序时,我们得到以下结果 -
    
    Student attempted 1 times to pass
    Student attempted 1 times to pass
    Student attempted 1 times to pass
    Student attempted 5 times to pass
    Student attempted 5 times to pass
    Student is absent for exam
    Student attempted 5 times to pass
    Student is absent for exam
    
  • 仅类协议

    当定义了协议并且用户想用类定义协议时,应该通过首先定义类然后是协议的继承列表来添加它。
    
    protocol tcpprotocol {
       init(no1: Int)
    }
    class mainClass {
       var no1: Int        // local storage
       init(no1: Int) {
          self.no1 = no1  // initialization
       }
    }
    class subClass: mainClass, tcpprotocol {
       var no2: Int
       init(no1: Int, no2 : Int) {
          self.no2 = no2
          super.init(no1:no1)
       }
       
       // Requires only one parameter for convenient method
       required override convenience init(no1: Int) {
          self.init(no1:no1, no2:0)
       }
    }
    let res = mainClass(no1: 20)
    let print = subClass(no1: 30, no2: 50)
    print("res is: \(res.no1)")
    print("res is: \(print.no1)")
    print("res is: \(print.no2)")
    
    当我们使用操场运行上述程序时,我们得到以下结果 -
    
    res is: 20
    res is: 30
    res is: 50
    
  • 协议组成

    Swift 4 允许在协议组合的帮助下一次调用多个协议。

    句法

    
    protocol<SomeProtocol, AnotherProtocol>
    

    例子

    
    protocol stname {
       var name: String { get }
    }
    protocol stage {
       var age: Int { get }
    }
    struct Person: stname, stage {
       var name: String
       var age: Int
    }
    func print(celebrator: stname & stage) {
       print("\(celebrator.name) is \(celebrator.age) years old")
    }
    let studname = Person(name: "Priya", age: 21)
    print(studname)
    let stud = Person(name: "Rehan", age: 29)
    print(stud)
    let student = Person(name: "Roshan", age: 19)
    print(student)
    
    当我们使用操场运行上述程序时,我们得到以下结果 -
    
    Person(name: "Priya", age: 21)
    Person(name: "Rehan", age: 29)
    Person(name: "Roshan", age: 19)
    
  • 检查协议一致性

    协议一致性由类似于类型转换的“is”和“as”运算符测试。
    • 如果实例符合协议标准,则 is 运算符返回 true,如果失败则返回 false。
    • as? 向下转型运算符的版本返回协议类型的可选值,如果实例不符合该协议,则该值为零。
    • 向下转换运算符的 as 版本强制向下转换为协议类型,如果向下转换不成功,则会触发运行时错误。
    
    import Foundation
    @objc protocol rectangle {
       var area: Double { get }
    }
    @objc class Circle: rectangle {
       let pi = 3.1415927
       var radius: Double
       var area: Double { return pi * radius * radius }
       init(radius: Double) { self.radius = radius }
    }
    @objc class result: rectangle {
       var area: Double
       init(area: Double) { self.area = area }
    }
    class sides {
       var rectsides: Int
       init(rectsides: Int) { self.rectsides = rectsides }
    }
    let objects: [AnyObject] = [Circle(radius: 2.0),result(area:198),sides(rectsides: 4)]
    for object in objects {
       if let objectWithArea = object as? rectangle {
          print("Area is \(objectWithArea.area)")
       } else {
          print("Rectangle area is not defined")
       }
    }
    
    当我们使用操场运行上述程序时,我们得到以下结果 -
    
    Area is 12.5663708
    Area is 198.0
    Rectangle area is not defined