Protokol pantas
Protokol menentukan kaedah dan atribut yang diperlukan untuk melaksanakan fungsi tertentu.
Sebarang jenis yang boleh memenuhi keperluan protokol dikatakan mematuhi protokol.
Kelas, struktur atau jenis penghitungan boleh mengikut protokol dan menyediakan pelaksanaan khusus untuk melengkapkan kaedah dan fungsi yang ditakrifkan oleh protokol.
Sintaks
Format sintaks protokol adalah seperti berikut:
protocol SomeProtocol { // 协议内容 }
Untuk menjadikan kelas mengikut protokol tertentu, anda perlu menambah nama protokol selepas nama jenis , dipisahkan oleh titik bertindih:, sebagai sebahagian daripada definisi jenis. Apabila mengikuti berbilang protokol, pisahkan dengan koma.
struct SomeStructure: FirstProtocol, AnotherProtocol { // 结构体内容 }
Jika kelas mempunyai kelas induk sambil mematuhi protokol, nama kelas induk hendaklah diletakkan sebelum nama protokol, dipisahkan dengan koma.
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol { // 类的内容 }
Spesifikasi atribut
Protokol digunakan untuk menentukan atribut instance atau atribut kelas tertentu tanpa menyatakan sama ada ia adalah atribut yang disimpan atau atribut yang dikira. Selain itu, ia mesti dinyatakan sama ada ia boleh dibaca sahaja atau boleh dibaca dan boleh ditulis.
Dalam protokol, var biasanya digunakan untuk mengisytiharkan atribut pembolehubah { set get } ditambah selepas pengisytiharan jenis untuk menunjukkan bahawa atribut boleh dibaca dan boleh ditulis diwakili oleh { 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)
Output pelaksanaan program di atas ialah:
98 true false Swift 协议 Swift
Peruntukan untuk kaedah Pengubahsuaian
Kadangkala perlu menukar contohnya dalam kaedah.
Contohnya, dalam kaedah contoh jenis nilai (struktur, penghitungan), kata kunci yang bermutasi digunakan sebagai awalan fungsi dan ditulis sebelum func, menunjukkan bahawa tika itu dimiliki dan contohnya boleh diubah suai dalam kaedah.
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()
Output pelaksanaan program di atas ialah:
Wednesday
Peruntukan untuk pembina
Protokol boleh memerlukan pengikutnya untuk melaksanakan pembina yang ditentukan.
Anda boleh menulis pengisytiharan pembina dalam definisi protokol sama seperti menulis pembina biasa, tetapi anda tidak perlu menulis pendakap kerinting dan entiti pembina Sintaksnya adalah seperti berikut:
protocol SomeProtocol { init(someParameter: Int) }
Contoh
protocol tcpprotocol { init(aprot: Int) }
Pembina protokol menentukan pelaksanaan dalam kelas
Anda boleh melaksanakan pembina dalam kelas yang mengikuti protokol dan menentukannya sebagai pembina yang ditetapkan atau kemudahan Pembina kelas. Dalam kedua-dua kes, anda mesti menandakan pelaksanaan pembina dengan pengubah "diperlukan":
class SomeClass: SomeProtocol { required init(someParameter: Int) { // 构造器实现 } } protocol tcpprotocol { init(aprot: Int) } class tcpClass: tcpprotocol { required init(aprot: Int) { } }
Menggunakan pengubah yang diperlukan memastikan semua subkelas yang mengikuti protokol ini juga boleh digunakan sebagai pembina Menentukan untuk menyediakan pelaksanaan eksplisit atau diwarisi pelaksanaan.
Jika subkelas mengatasi pembina yang ditetapkan bagi kelas induk, dan pembina mematuhi peruntukan protokol tertentu, maka pelaksanaan pembina perlu ditandakan dengan kedua-dua pengubah yang diperlukan dan mengatasi:
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)")
Hasil keluaran pelaksanaan program di atas ialah:
res is: 20 res is: 30 res is: 50
Jenis protokol
Walaupun protokol itu sendiri tidak melaksanakan sebarang fungsi, protokol boleh digunakan sebagai jenis.
Protokol boleh digunakan seperti jenis biasa lain, senario penggunaan:
sebagai jenis parameter atau jenis nilai pulangan dalam fungsi, kaedah atau pembina
Sebagai jenis pemalar, pembolehubah atau sifat
Sebagai jenis elemen dalam tatasusunan, kamus atau bekas lain
Contoh
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}))
Hasil output pelaksanaan program di atas ialah:
10 20 30 5 10 15 [100, 200, 300] [10, 20, 30]
Tambah ahli protokol dalam sambungan
Kami boleh melanjutkan jenis sedia ada (kelas, struktur, penghitungan, dll.) melalui sambungan.
Sambungan boleh menambah atribut, kaedah, skrip subskrip, protokol dan ahli lain pada jenis sedia ada.
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" } } }
Warisan protokol
Sesuatu protokol boleh mewarisi satu atau lebih protokol lain dan keperluan kandungan baharu boleh ditambah berdasarkan protokol yang diwarisi.
Sintaks warisan protokol adalah serupa dengan beberapa protokol yang diwarisi dipisahkan dengan koma: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)
Hasil keluaran pelaksanaan program di atas Untuk:
学生尝试 1 次通过 学生尝试 1 次通过 学生尝试 1 次通过 学生尝试 5 次通过 学生尝试 5 次通过 学生缺席考试 学生尝试 5 次通过 学生缺席考试
Protokol khusus kelas
Anda boleh mengehadkan protokol untuk hanya menyesuaikan diri dengan jenis kelas dengan menambahkan kata kunci kelas dalam senarai warisan protokol.
Kata kunci kelas mestilah yang pertama muncul dalam senarai warisan protokol, diikuti oleh protokol warisan lain. Formatnya adalah seperti berikut:
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)")
Output pelaksanaan program di atas ialah:
res is: 20 res is: 30 res is: 50
Sintesis Protokol
Swift supports sintesis berbilang protokol Ini sangat berguna apabila kita perlu mengikuti berbilang protokol pada masa yang sama.
Format sintaks adalah seperti berikut:
protocol<SomeProtocol, AnotherProtocol>
Contoh
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)
Hasil output pelaksanaan program di atas ialah:
Person(name: "Priya", age: 21) Person(name: "Rehan", age: 29) Person(name: "Roshan", age: 19)
Semak konsistensi protokol
Anda boleh menggunakan is dan sebagai operator untuk menyemak sama ada protokol tertentu diikuti atau penukaran paksa kepada jenis tertentu. Pengendali
is
digunakan untuk menyemak sama ada tika遵循
mempunyai协议
tertentu.as?
Mengembalikan nilai pilihan yang mengembalikan jenis protokol apabila protokol遵循
dimulakan jika tidak,nil
dikembalikan.as
digunakan untuk memaksa penukaran ke bawah Jika penukaran paksa gagal, ralat masa jalan akan berlaku.
Contoh
Contoh berikut mentakrifkan protokol HasArea, memerlukan kawasan boleh dibaca jenis Double:
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("没有面积") } }
Output pelaksanaan program di atas Hasilnya ialah:
面积为 12.5663708 面积为 243610.0 没有面积