با عرض سلام و وقت بخیر خدمت کاربران سایت پی وی لرن . و کاربرانی که دوره کامل آموزش Swift را دنبال می کنند. پروتکل ها یک طرح برای متدها، خصوصیات و سایر قابلیت های مورد نیاز را ارائه می دهند. این فقط به عنوان یک متد یا خصوصیات کلی به جای پیاده سازی توصیف شده است. پیاده سازی متد ها و خصوصیات می تواند با تعریف کلاس ها، توابع و شمارنده ها انجام شود. سازگاری یک پروتکل به عنوان متد یا خصوصیات مورد نیاز الزامات پروتکل تعریف می شود. برای آشنایی بیشتر با مبحث پروتکل ها در Swift در ادامه ی این بخش با ما همراه باشید.
در این آموزش شما را با سینتکس و مباحث مربوط به پروتکل ها در Swift آشنا می کنیم.
پروتکل ها نیز از سینتکس مشابه کلاس ها، ساختارها و فهرست ها استفاده می کنند :
1 2 3 | protocol SomeProtocol { // protocol definition } |
پروتکل ها بعد از طبقه بندی، ساختار یا نام های نوع شمارنده ها اعلام می شوند. اعلامیه های پروتکل تک و چندگانه نیز امکان پذیر است.
اگر چندین پروتکل تعریف شده باشند، باید با کاما از هم جدا شوند:
1 2 3 | struct SomeStructure: Protocol1, Protocol2 { // structure definition } |
وقتی یک پروتکل برای ابر کلاس تعریف می شود، نام پروتکل باید با نام کامپوننت ابر کلاس دنبال شود:
1 2 3 | class SomeClass: SomeSuperclass, Protocol1, Protocol2 { // class definition } |
پروتکل برای مشخص کردن خصوصیت نوع کلاس خاص و یا خصوصیت نوع استفاده می شود.
این فقط ویژگی نوع یا نمونه را فقط به جای مشخص کردن اینکه آیا یک نوع ذخیره شده یا محاسبه شده است، مشخص می کند.
همچنین مشخص می کند که یک ویژگی شامل ‘gettable’ یا ‘settable’ می شود.
نیازهای یک خصوصیت با کلمه ی کلیدی ‘var’ به عنوان خصوصیت اعلام می شود.
{get set} برای اعلام gettable استفاده می شود و خصوصیات settable بعد از اعلام نوع قرار دارد.
Gettable با خصوصیت {get} بعد از اعلام نوع تعریف شده است.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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) |
نتیجه ی کامپایل و اجرای کد فوق به صورت زیر خواهد بود:
1 2 3 4 5 | 98 true false Swift 4 Protocols Swift 4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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() |
نتیجه ی کامپایل و اجرای کد فوق به صورت زیر خواهد بود:
1 | Wednesday |
نوسان اجازه می دهد تا کاربر برای راه اندازی پروتکل ها به دنبال نوع انطباق شبیه به آن از برنامه های اولیه طبیعی باشد.
1 2 3 | protocol SomeProtocol { init(someParameter: Int) } |
به عنوان مثال :
1 2 3 | protocol tcpprotocol { init(aprot: Int) } |
initializer های Designated یا convenience به کاربر اجازه می دهد تا برای مقداردهی اولیه ی استاندارد یک پروتکل از کلمه کلیدی ‘required’ استفاده کند:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class SomeClass: SomeProtocol { required init(someParameter: Int) { // initializer implementation statements } } protocol tcpprotocol { init(aprot: Int) } class tcpClass: tcpprotocol { required init(aprot: Int) { } } |
انطباق پروتکل در همه زیر کلاسها برای اجرای صریح یا ارثی با مادیفایر ‘required’ پیاده سازی شده است.
هنگامی که یک زیرگروه نیاز اولیه آن را به ابر کلاس متوقف می کند، با کلمه کلیدی مادیفایر ‘override’ مشخص می شود.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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) } 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)") |
نتیجه ی کامپایل و اجرای کد فوق به صورت زیر خواهد بود:
1 2 3 | res is: 20 res is: 30 res is: 50 |
به جای اجرای ویژگی ها در یک پروتکل، آنها به عنوان انواع توابع، کلاس ها، متد ها و… مورد استفاده قرار می گیرند.
پروتکل ها می توانند به انواع زیر دسترسی داشته باشند :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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})) |
نتیجه ی کامپایل و اجرای کد فوق به صورت زیر خواهد بود:
1 2 3 4 5 6 7 8 | 10 20 30 5 10 15 [100, 200, 300] [10, 20, 30] |
با استفاده از افزونه ها، نوع موجود می تواند مورد استفاده قرار گیرد و با یک پروتکل جدید سازگار باشد.
خصوصیات جدید، متدها و شاخص ها می توانند به کمک انواع extensions ها به انواع موجود اضافه شوند.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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 اجازه می دهد که پروتکل ها خصوصیات را از خصوصیات مشخص شده به ارث ببرند.
این شبیه به وراث کلاس است، اما با انتخاب فهرست چند پروتکل ارثی که توسط کاما جدا شده اند.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 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) |
نتیجه ی کامپایل و اجرای کد فوق به صورت زیر خواهد بود:
1 2 3 4 5 6 7 8 | 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 |
هنگامی که پروتکل ها تعریف می شود و کاربر می خواهد پروتکل را با کلاس تعریف کند باید با تعریف کلاس اول به دنبال لیست ارثی پروتکل اضافه شود.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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)") |
نتیجه ی کامپایل و اجرای کد فوق به صورت زیر خواهد بود:
1 2 3 | res is: 20 res is: 30 res is: 50 |
Swift 4 اجازه می دهد پروتکل های چندگانه در قالب یکی با کمک ترکیب پروتکل ها فرخوانی شوند.
1 | protocol<SomeProtocol, AnotherProtocol> |
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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) |
نتیجه ی کامپایل و اجرای کد فوق به صورت زیر خواهد بود:
1 2 3 | Person(name: "Priya", age: 21) Person(name: "Rehan", age: 29) Person(name: "Roshan", age: 19) |
انطباق پروتکل توسط عملگرهای “is” و “as” آزمایش شده است که مشابه نوع ریخته گری است.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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") } } |
نتیجه ی کامپایل و اجرای کد فوق به صورت زیر خواهد بود:
1 2 3 | Area is 12.5663708 Area is 198.0 Rectangle area is not defined |
ساختار پروتکل ها در Swift به برنامه نویس اجازه می دهد تا از قابلیت هایی مانند ساختار و کلاس ها را بصورت کامل تر و و جزئیات بیشتر در برنامه ی خود استفاده کند، از این رو پروتکل جایگزین مناسبی برای اینگونه ساختارها در Swift می باشد.