با عرض سلام و وقت بخیر خدمت کاربران سایت پی وی لرن . و کاربرانی که دوره کامل آموزش Swift را دنبال می کنند. محدود کردن دسترسی به بلوک های کد، ماژول ها و انتزاع در Swift از طریق Access control (کنترل دسترسی) انجام می شود. کلاس ها، سازه ها و شمارنده ها می توانند با توجه به خصوصیات، متد ها، واسطه ها و شاخص های آنها با مکانیزم های کنترل دسترسی قابل دسترسی باشند. ثابت ها، متغیرها و توابع در یک پروتکل در قالب عمومی و محلی از طریق کنترل دسترسی قابل محدودیت و مجاز به دسترسی است. ویژگی کنترل دسترسی در Swift به خصوصیات اعمال می شود، به نوع ها و توابع نیز می توان به عنوان ‘entities’ (موجودیت) اشاره کرد.
در این آموزش شما با سینتکس کلی ویژگی کنترل دسترسی در Swift و کار با آن در انواع ساختارها آشنا می شوید.
مدل ویژگی Access control به ماژول ها و سورس های منبع بستگی دارد.
ماژول به عنوان یک واحد تکی از کد توزیع تعریف شده است و می توان با کلمه کلیدی ‘import’ آن را وارد کرد.
یک فایل منبع به عنوان یک فایل کد منبع تکی، با یک ماژول برای دسترسی به انواع و توابع چندگانه تعریف شده است.
سه سطح دسترسی متفاوت توسط زبان Swift 4 ارائه شده است، که شامل دسترسی عمومی ، داخلی و خصوصی می شود.
ردیف | سطح دسترسی و تعریف |
---|---|
۱ | Public موجودیت ها را قادر می سازد تا در هر فایل منبع از ماژول تعیین شده خود، یک فایل منبع از ماژول دیگری که وارد ماژول تعریف می شود، پردازش شود. |
۲ | Internal موجودیت ها را قادر می سازد در هر فایل منبع از ماژول تعریف شده ما استفاده شود، اما در هر فایل منبعی خارج از آن ماژول اینطور نیست. |
۳ | Private استفاده از یک موجودیت را به فایل منبع تعریف خود محدود می کند. |
1 2 3 4 5 6 7 | public class SomePublicClass {} internal class SomeInternalClass {} private class SomePrivateClass {} public var somePublicVariable = 0 internal let someInternalConstant = 0 private func somePrivateFunction() {} |
بعضی از توابع ممکن است آرگومان های داخل تابع را بدون هیچ مقدار بازگشتی اعلام کنند.
برنامه زیر مقدار ۱ و b را به عنوان آرگومان به تابع () sum می دهد.
در داخل تابع ، مقادیر برای آرگومان های a و b با فراخوانی () sum فراخوانی می شود و مقادیر آن چاپ شده و از این طریق مقادیر بازگشتی را حذف می کنند.
برای ایجاد نوع بازگشتی تابع به عنوان خصوصی، سطح دسترسی کلی تابع را با مادیفایر خصوصی اعلام کنید.
مثال :
1 2 3 4 5 6 7 8 9 | private func sum(a: Int, b: Int) { let a = a + b let b = a - b print(a, b) } sum(a: 20, b: 10) sum(a: 40, b: 10) sum(a: 24, b: 6) |
نتیجه ی کامپایل و اجرای کد فوق:
1 2 3 | 30 20 50 40 30 24 |
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public enum Student { case Name(String) case Mark(Int,Int,Int) } var studDetails = Student.Name("Swift 4") var studMarks = Student.Mark(98,97,95) switch studMarks { case .Name(let studName): print("Student name is: \(studName).") case .Mark(let Mark1, let Mark2, let Mark3): print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).") } |
نتیجه ی کامپایل و اجرای کد فوق:
1 | Student Marks are: 98,97,95 |
شمارنده ها در Swift 4 بصورت خودکار یک سطح دسترسی را برای موارد شاخص یک شمارنده دریافت می کنند.
به عنوان مثال برای دسترسی به نام های دانش آموزان که در یک کلاس از نوع string تعریف شده و با سه متغیر mark1, mark2 و mark3 از نوع integer قابل مشاهده است.
در حالت معمول نام دانش آموز چاپ می شود و در صورتی که بلوک مورد نظر اجرا شود. mark هایی که برای نام دانش آموزان مشخص شده چاپ می شود.
در صورتی ک هیچکدام از موارد بالا انجام نشود بلوک پیش فرض اجرا می شود.
Swift 4 اجازه می دهد که کاربر به زیر کلاس هر کلاس بتواند دسترسی داشته باشد.
یک زیر کلاس نمی تواند سطح دسترسی بالاتری از ابر کلاس داشته باشد.
کاربر از نوشتن یک زیر مجموعه عمومی یک ابر کلاس خصوصی محدود شده است.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class cricket { internal func printIt() { print("Welcome to Swift 4 Super Class") } } internal class tennis: cricket { override internal func printIt() { print("Welcome to Swift 4 Sub Class") } } let cricinstance = cricket() cricinstance.printIt() let tennisinstance = tennis() tennisinstance.printIt() |
نتیجه ی کامپایل و اجرای کد فوق:
1 2 | Welcome to Swift Super Class Welcome to Swift Sub Class |
ثابت ها، متغیرها یا خصوصیات Swift 4 نمی تواند به عنوان عمومی تعریف شوند.
نمی توان یک خصوصیت عمومی را با یک نوع خصوصی نوشت.
به طور مشابه، یک زیر مجموعه نمی تواند عمومی تر از شاخص یا نوع بازگشتی آن باشد.
هنگامی که یک متغیر مستقل، متغیر، خصوصیت یا زیر مجموعه از یک نوع خصوصی انجام می دهد، ثابت، متغیر، خصوصیت یا زیرمجموعه نیز باید به صورت خصوصی مشخص شود:
1 | private var privateInstance = SomePrivateClass() |
Getter ها و setter ها برای ثابت ها ، متغیر ها ، خصوصیات و زیر مجموعه ها به طور خودکار یک سطح دسترسی را به عنوان ثابت ، متغیر ، خصوصیت یا زیر مجموعه ای که به آن ها تعلق دارد دریافت می کند.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Samplepgm { var counter: Int = 0{ willSet(newTotal) { print("Total Counter is: \(newTotal)") } didSet { if counter > oldValue { print("Newly Added Counter \(counter - oldValue)") } } } } let NewCounter = Samplepgm() NewCounter.counter = 100 NewCounter.counter = 800 |
نتیجه ی کامپایل و اجرای کد فوق:
1 2 3 4 | Total Counter is: 100 Newly Added Counter 100 Total Counter is: 800 Newly Added Counter 700 |
initializer های سفارشی می تواند به یک سطح دسترسی کوچکتر و یا مساوی نوعی که مقداردهی اولیه شدند تخصیص یابد.
Initiator لازم است که همان سطح دسترسی را به عنوان کلاس متعلق به آن داشته باشد.
انواع پارامترهای اولیه نمی تواند خصوصی تر از سطح دسترسی خصوصی خود باشد.
برای اعلام هر زیر کلاس از مقداردهی اولیه کلمه کلیدی ‘required’ برای نعریف قبل از تابع ()init نیاز است.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class classA { required init() { let a = 10 print(a) } } class classB: classA { required init() { let b = 30 print(b) } } let res = classA() let print = classB() |
نتیجه ی کامپایل و اجرای کد فوق:
1 2 3 | 10 30 10 |
یک initializer پیش فرض یک سطح دسترسی را به عنوان نوع آن initializes داراست مگر اینکه این نوع به عنوان عمومی تعریف شده باشد.
وقتی که initialize پیش فرض به عنوان نوع عمومی داخلی در نظر گرفته شده و کاربر نیاز به یک نوع عمومی بدون آرگومان بدون initializes دارد، یک initializer بدون آرگومان ارائه می شود.
هنگامی که ما یک پروتکل جدید را برای به رسمیت شناختن ویژگی ها از یک پروتکل موجود تعریف می کنیم، هر دو باید سطوح دسترسی مجزایی را برای به ارث بردن خواص یکدیگر تعریف کنند.
کنترل دسترسی 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 | public protocol tcpprotocol { init(no1: Int) } public 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 کاربران را مجبور به ارائه یک مادیفایر سطح دسترسی صریح برای یک برنامه افزودنی می کند.
سطح دسترسی پیش فرض برای هر پیاده سازی مورد نیاز پروتکل درون پسوند با سطح دسترسی پروتکل خود به خود ارائه می شود.
Generic ها اجازه می دهند که کاربر حداقل سطوح دسترسی را برای دسترسی به محدودیت های نوع پارامترها مشخص کند.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public struct TOS<T> { var items = [T]() mutating func push(item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() } } var tos = TOS<String>() tos.push(item: "Swift 4") print(tos.items) tos.push(item: "Generics") print(tos.items) tos.push(item: "Type Parameters") print(tos.items) tos.push(item: "Naming Type Parameters") print(tos.items) let deletetos = tos.pop() |
نتیجه ی کامپایل و اجرای کد فوق:
1 2 3 4 | [Swift 4] [Swift 4, Generics] [Swift 4, Generics, Type Parameters] [Swift 4, Generics, Type Parameters, Naming Type Parameters] |
کاربر می تواند انواع اسامی مستعار را برای انواع دسترسی مجاز تعریف کند.
سطح دسترسی و یا سطوح دسترسی مختلف می تواند توسط کاربر تعریف شود.
زمانیکه نوع اسامی مستعار ‘private’ باشد اعضای مرتبط آن می توان به صورت ‘private’ یا نوع عمومی داخلی تعریف شود.
وقتیکه نوع اسامی مستعار عمومی (public) باشد اعضای آن نمی تواند نام مستعار از نوع ‘internal’ یا ‘private’ داشته باشد.
هر گونه نام های مستعار که شما تعریف می کنید به عنوان انواع متمایز برای اهداف کنترل دسترسی مورد استفاده قرار می گیرند.
یک نوع نام مستعار می تواند سطح دسترسی کمتر یا برابر با سطح دسترسی آن نوع اسامی مستعار را داشته باشند.
برای مثال یک نوع نام مستعار private می تواند به نوع های private, internal یا public اعمال شود.
اما یک نوع نام مستعار public نمی تواند به عنوان نام مستعار داخلی یا private در نظر گرفته شود.
مثال :
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 53 54 55 56 57 58 | public protocol Container { associatedtype ItemType mutating func append(item: ItemType) var count: Int { get } subscript(i: Int) -> ItemType { get } } struct Stack<T>: Container { // original Stack<T> implementation var items = [T]() mutating func push(item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() } // conformance to the Container protocol mutating func append(item: T) { self.push(item: item) } var count: Int { return items.count } subscript(i: Int) -> T { return items[i] } } func allItemsMatch< C1: Container, C2: Container where C1.ItemType == C2.ItemType, C1.ItemType: Equatable> (someContainer: C1, anotherContainer: C2) -> Bool { // check that both containers contain the same number of items if someContainer.count != anotherContainer.count { return false } // check each pair of items to see if they are equivalent for i in 0..<someContainer.count { if someContainer[i] != anotherContainer[i] { return false } } // all items match, so return true return true } var tos = Stack<String>() tos.push(item: "Swift 4") print(tos.items) tos.push(item: "Generics") print(tos.items) tos.push(item: "Where Clause") print(tos.items) var eos = ["Swift 4", "Generics", "Where Clause"] print(eos) |
نتیجه ی کامپایل و اجرای کد فوق:
1 2 3 4 | [Swift 4] [Swift 4, Generics] [Swift 4, Generics, Where Clause] [Swift 4, Generics, Where Clause] |
Swift 4 یک پروتکل Codable جدید را معرفی می کند که اجازه می دهد سریال های شما بدون نوشتن کد خاص و بدون نیاز به نگرانی در مورد از دست دادن انواع ارزش های خود، استفاده کنید.
مثال :
1 2 3 4 5 6 7 | struct Language: Codable { var name: String var version: Int } let swift = Language(name: "Swift", version: 4) let java = Language(name: "java", version: 8) let R = Language(name: "R", version: 3 |
توجه داشته باشید که زبان سازگار با پروتکل Codable است.
حالا ما آن را به نمایندگی داده Json با استفاده از یک خط ساده تبدیل می کنیم:
1 2 3 4 | let encoder = JSONEncoder() if let encoded = try? encoder.encode(java) { } |
Swift به صورت خودکار تمام مقادیر داخل نوع داده ی شما را encode می کند.
شما می توانید با استفاده از تابع Decoder داده را encode کنید:
1 2 3 | let decoder = JSONDecoder() if let decoded = try? decoder.decode(Language.self, from: encoded) { } |
هر دو نوع JSONEncoder و PropertyListEncoder گزینه های زیادی را برای سفارشی کردن چگونگی عملکرد خود دارند.
مکانیزم کنترل دسترسی در Swift را می توان بر انواع ساختارها از جمله ، ثابت ها، متغیرها ، خصوصیات ، توابع و … اعمال کرد و با این ویژگی می توان سطح دسترسی عمومی ، خصوصی و … را برای آن ها تعیین کرد.
geeekboy92
این قسمت آخر بود ؟
علی اصغری
سلام ، بله این دوره بیشتر مناسب افراد مبتدی هست اما به احتمال زیاد در آینده دوره پیشرفته رو خواهیم داشت.