Swift protocol
The protocol specifies the methods and attributes necessary to implement a specific function.
Any type that can meet the requirements of the protocol is called conforming to the protocol.
Classes, structures or enumeration types can all follow the protocol 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 { // 协议内容 }
To make the class follow a certain protocol, you need to add the protocol name after the type name, separated by a colon:, as part of the type definition. When following multiple protocols, separate each protocol with a comma.
struct SomeStructure: FirstProtocol, AnotherProtocol { // 结构体内容 }
If a class has a parent class while complying with the protocol, the parent class name should be placed before the protocol name, separated by commas.
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol { // 类的内容 }
Provisions for properties
The protocol is used to specify specific instance properties or class properties without specifying whether they are stored properties or computed properties. In addition, it must be specified whether it is read-only or readable and writable.
In the protocol, var is usually used to declare variable attributes. { set get } is added after the type declaration to indicate that the attribute is readable and writable. Read-only attributes are represented by { 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 execution output of the above program is:
98 true false Swift 协议 Swift
Provisions for the Mutating method
Sometimes it is necessary to change its instance in the method.
For example, in an instance method of a value type (structure, enumeration), the mutating keyword is used as the prefix of the function and is written before func, indicating that the instance and its instance to which it belongs can be modified in the method. The value of the attribute.
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 execution output of the above program is:
Wednesday
Provisions for constructors
The protocol can require its followers to implement the specified constructor.
You can write the declaration of the constructor in the protocol definition just like writing a normal constructor, but you do not need to write the curly braces and the entity of the constructor. The syntax is as follows:
protocol SomeProtocol { init(someParameter: Int) }
Example
protocol tcpprotocol { init(aprot: Int) }
The protocol constructor specifies the implementation in the class
You can implement the constructor in the class that follows the protocol and specify it as the designated constructor or convenience of the class Constructor. In both cases, you must mark 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 subclasses that follow this protocol can also be used as constructors Specifies to provide an explicit implementation or inherited implementation.
If a subclass overrides the designated constructor of the parent class, and the constructor complies with the provisions of a certain protocol, then 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 execution output of the above program is:
res is: 20 res is: 30 res is: 50
Protocol type
Although the protocol itself does not implement any function, the protocol can be used as a type.
Protocols can be used like other ordinary types. Usage scenarios:
As a parameter type or return value type in a function, method or constructor
As a type of a constant, variable, or property
As a type of an element in an array, dictionary, or other container
Example
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 result of the above program execution is:
10 20 30 5 10 15 [100, 200, 300] [10, 20, 30]
Add protocol members in extension
We can extend existing types (classes, structures, enumerations, etc.) through extensions.
Extensions can add attributes, methods, subscript 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" } } }
Inheritance of protocol
A protocol can inherit one or more other protocols, and new content requirements can be added based on the inherited protocol.
The inheritance syntax of the protocol is similar to the inheritance of the class. Multiple inherited protocols are separated by commas:protocol InheritingProtocol: SomeProtocol, AnotherProtocol { // 协议定义 }
Example
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 above program execution output results For:
学生尝试 1 次通过 学生尝试 1 次通过 学生尝试 1 次通过 学生尝试 5 次通过 学生尝试 5 次通过 学生缺席考试 学生尝试 5 次通过 学生缺席考试
Class-specific protocol
You can restrict the protocol to only adapt to class types by adding the class keyword in the protocol's inheritance list.
The class keyword must be the first one to appear in the inheritance list of the protocol, followed by other inherited protocols. The format is as follows:
protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol { // 协议定义 }
Example
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 execution output of the above program is:
res is: 20 res is: 30 res is: 50
Protocol synthesis
Swift supports the synthesis of multiple protocols. This is very useful when we need to follow multiple protocols at the same time.
The syntax format is as follows:
protocol<SomeProtocol, AnotherProtocol>
Example
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 above program execution output result is:
Person(name: "Priya", age: 21) Person(name: "Rehan", age: 29) Person(name: "Roshan", age: 19)
Check the consistency of the protocol
You can use the is and as operators to check whether a certain protocol is followed or forced conversion to a certain type. The
is
operator is used to check whether the instancefollows
a certainprotocol
.as?
Returns an optional value. When the instancefollows the
protocol, return the protocol type; otherwise returnnil
.#as
is used to force downward conversion. If the forced conversion fails, a runtime error will occur.
Example
The following example defines a HasArea protocol, requiring 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 above program execution output The result is:
面积为 12.5663708 面积为 243610.0 没有面积