Swift protocol
The protocol specifies the methods and properties necessary to implement a particular function.
Any type that meets the requirements of the protocol is called the conform protocol.
Classes, structures, or enumeration types can all follow protocols and provide specific implementations to complete the methods and functions defined by the protocol.
Grammar
The syntax format of the protocol is as follows:
protocol SomeProtocol { // 协议内容 }
For a class to follow a protocol, you need to add the protocol name after the type name, with a colon in the middle: separated, as part of the type definition. When following multiple protocols, the protocols are separated by commas.
struct SomeStructure: FirstProtocol, AnotherProtocol { // 结构体内容 }
If the class has a parent class while following the protocol, the parent class name should be placed before the protocol name, separated by a comma.
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol { // 类的内容 }
The rule for the property
Protocols are used to specify specific instance or class properties, not storage or computational properties. You must also indicate whether it is read-only or readable.
Variable properties are usually declared with var in the protocol, and after the type declaration, the property is readable and writeable, and read-only properties are represented by the word "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 协议" 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" studdet.marks = 98 studdet.markssecured() print(studdet.marks) print(studdet.result) print(studdet.present) print(studdet.subject) print(studdet.stname)
The output of the above program execution is:
98 true false Swift 协议 Swift
Regulations on the Mutating method
Sometimes you need to change its instance in the method.
For example, in an instance method of a value type (structure, enumeration), the muting keyword is prefixed as a function and written before func, indicating that the value of the instance to which it belongs and its instance properties can be modified in that method.
protocol daysofaweek { mutating func show() } enum days: daysofaweek { case sun, mon, tue, wed, thurs, fri, sat mutating func show() { 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.show()
The output of the above program execution is:
Wednesday
The regulation of the constructor
The protocol can require its adherer to implement the specified constructor.
You can write the constructor's declaration in the definition of the protocol, just as you would a normal constructor, but you don't need to write parentheses and constructor entities, as in the following syntax:
protocol SomeProtocol { init(someParameter: Int) }
Instance
protocol tcpprotocol { init(aprot: Int) }
The protocol constructor specifies the implementation in the class
You can implement constructors in classes that follow this protocol and specify them as specified constructors or convenience constructors for classes. In both cases, you must label the constructor implementation with the "required" modifier:
class SomeClass: SomeProtocol { required init(someParameter: Int) { // 构造器实现 } } protocol tcpprotocol { init(aprot: Int) } class tcpClass: tcpprotocol { required init(aprot: Int) { } }
Using the required modifier ensures that all sub-classes that follow the protocol can also provide an explicit implementation or inheritance implementation for constructor provisions.
If a child class rewrites the specified constructor of the parent class, and the constructor follows the provisions of a protocol, the implementation of the constructor needs to be marked with both the required and override modifiers:
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) } } let res = mainClass(no1: 20) let show = subClass(no1: 30, no2: 50) print("res is: \(res.no1)") print("res is: \(show.no1)") print("res is: \(show.no2)")
The output of the above program execution is:
res is: 20 res is: 30 res is: 50
The type of protocol
Although the protocol itself does not implement any functionality, the protocol can be used as a type.
Protocols can be used like other normal types, using scenarios:
- As an argument type or return value type in a function, method, or constructor
- The type of constant, variable, or property
- As the type of element in an array, dictionary, or other container
Instance
protocol Generator { typealias members func next() -> members? } var items = [10,20,30].generate() while let x = items.next() { print(x) } for lists in [1,2,3].map( {i in i*5}) { print(lists) } print([100,200,300]) print([1,2,3].map({i in i*10}))
The output of the above program execution is:
10 20 30 5 10 15 [100, 200, 300] [10, 20, 30]
Add protocol members to the extension
We can extend existing types (classes, structures, enumerates, etc.) by extending them.
Extensions can add properties, methods, underseed scripts, protocols, and other members to existing types.
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" } } }
The inheritance of the agreement
An agreement can inherit one or more other agreements, and new content requirements can be added to the inherited agreement.
The protocol's inheritance syntax is similar to that of a class, with multiple inherited protocols separated by commas:
protocol InheritingProtocol: SomeProtocol, AnotherProtocol { // 协议定义 }
Instance
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(1) } } class Classb: Result { func print(target: Classa) { target.calc(5) } } class Student: Classa { var no1: Int = 10 func calc(sum: Int) { no1 -= sum print("学生尝试 \(sum) 次通过") if no1 <= 0 { print("学生缺席考试") } } } class Player { var stmark: Result! init(stmark: Result) { self.stmark = stmark } func print(target: Classa) { stmark.print(target) } } var marks = Player(stmark: Student2()) var marksec = Student() marks.print(marksec) marks.print(marksec) marks.print(marksec) marks.stmark = Classb() marks.print(marksec) marks.print(marksec) marks.print(marksec)
The output of the above program execution is:
学生尝试 1 次通过 学生尝试 1 次通过 学生尝试 1 次通过 学生尝试 5 次通过 学生尝试 5 次通过 学生缺席考试 学生尝试 5 次通过 学生缺席考试
Class-specific protocols
You can limit the protocol to class types by adding the class keyword in the agreement's inheritance list.
The class keyword must be the first to appear in the agreement's inheritance list, followed by the other inheritance agreements. The format is as follows:
protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol { // 协议定义 }
Instance
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) } } let res = MainClass(no1: 20) let show = SubClass(no1: 30, no2: 50) print("res is: \(res.no1)") print("res is: \(show.no1)") print("res is: \(show.no2)")
The output of the above program execution is:
res is: 20 res is: 30 res is: 50
Protocol synthesis
Swift supports the synthesis of multiple protocols, which is useful when we need to follow multiple protocols at the same time.
The syntax format is as follows:
protocol<SomeProtocol, AnotherProtocol>
Instance
protocol Stname { var name: String { get } } protocol Stage { var age: Int { get } } struct Person: Stname, Stage { var name: String var age: Int } func show(celebrator: protocol<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)
The output of the above program execution is:
Person(name: "Priya", age: 21) Person(name: "Rehan", age: 29) Person(name: "Roshan", age: 19)
Test the consistency of the protocol
You can use the is and as operators to check if you follow a protocol or force conversion to a type.
-
is
operator is used to check that the遵循
a协议
-
as?
R eturns an optional value that returns the遵循
when the instance follows the agreement; Otherwise,nil
-
as
used to force a downward transition, which can cause runtime errors if a strong transition fails.
Instance
The following example defines a HasArea protocol that requires a Double type readable area:
protocol HasArea { var area: Double { get } } // 定义了Circle类,都遵循了HasArea协议 class Circle: HasArea { let pi = 3.1415927 var radius: Double var area: Double { return pi * radius * radius } init(radius: Double) { self.radius = radius } } // 定义了Country类,都遵循了HasArea协议 class Country: HasArea { var area: Double init(area: Double) { self.area = area } } // Animal是一个没有实现HasArea协议的类 class Animal { var legs: Int init(legs: Int) { self.legs = legs } } let objects: [AnyObject] = [ Circle(radius: 2.0), Country(area: 243_610), Animal(legs: 4) ] for object in objects { // 对迭代出的每一个元素进行检查,看它是否遵循了HasArea协议 if let objectWithArea = object as? HasArea { print("面积为 \(objectWithArea.area)") } else { print("没有面积") } }
The output of the above program execution is:
面积为 12.5663708 面积为 243610.0 没有面积