English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
يمكن تحديد مستوى الوصول للكود في ملفات المصدر أو الملتقيات الأخرى إلى الكود الخاص بك.
يمكن تعيين مستوى الوصول للنوع الخاص (فئة، بنية، جرد) بشكل واضح، وكذلك للخصائص والوظائف والمتغيرات الأساسية والمؤشرات الأساسية للنوع.
يمكن تحديد نطاق استخدام الاتفاقيات أيضًا، بما في ذلك الكيانات العالمية في الاتفاقية مثل الكيانات الثابتة والغير محددة.
يتم التحكم في الوصول بناءً على الملتقى وملف المصدر.
الملتقى هو وحدة مستقلة يتم بناؤها ونشرها كـ Framework أو تطبيق. يمكن استخدام كلمة المفتاح import لاستيراد ملتقى آخر في Swift.
ملف المصدر هو ملف المصدر الواحد، وهو عادة ما ينتمي إلى ملتقى، يمكن أن يحتوي ملف المصدر على تعريفات فئات ووظائف متعددة.
يقدم Swift أربعة مستويات مختلفة من الوصول للكيانات في الكود: public، internal، fileprivate، private.
مستوى الوصول | تعريف |
---|---|
public | يمكن الوصول إلى أي كيان في ملفات المصدر الخاصة بالملتقى، يمكن للآخرين أيضًا الوصول إلى جميع الكيانات في ملفات المصدر الخاصة بالملتقى من خلال استيراد هذا الملتقى. |
internal | يمكن الوصول إلى أي كيان في ملفات المصدر الخاصة بالملتقى، ولكن لا يمكن للآخرين الوصول إلى هذه الكيانات في ملفات المصدر الخاصة بالملتقى. |
fileprivate | خاص بالملف، يمكن استخدامه فقط داخل ملف المصدر الحالي. |
private | يمكن الوصول إليه داخل الفئة فقط، لا يمكن الوصول إليه خارج نطاق الفئة أو بنية المخطط. |
public هو مستوى الوصول الأعلى، private هو مستوى الوصول الأدنى.
يتم تعريف مستوى الوصول للكيانات من خلال التعديلات public، internal، fileprivate، private:
public class SomePublicClass {} internal class SomeInternalClass {} fileprivate class SomeFilePrivateClass {} private class SomePrivateClass {} public var somePublicVariable = 0 internal let someInternalConstant = 0 fileprivate func someFilePrivateFunction() {} private func somePrivateFunction() {}
إلا إذا كان هناك توجيه خاص، فإن جميع الكيانات تستخدم مستوى الوصول الافتراضي internal.
class SomeInternalClass {} // 访问级别为 internal let someInternalConstant = 0 // 访问级别为 internal
函数的访问级别需要根据该函数的参数类型和返回类型的访问级别得出。
下面的实例定义了一个名为someFunction全局函数,并且没有明确地申明其访问级别。
func someFunction() -> (SomeInternalClass, SomePrivateClass) { // 函数实现 {}
函数中其中一个类 SomeInternalClass 的访问级别是 internal,另一个 SomePrivateClass 的访问级别是 private。所以根据元组访问级别的原则,该元组的访问级别是 private(元组的访问级别与元组中访问级别最低的类型一致)。
因为该函数返回类型的访问级别是 private,所以你必须使用 private 修饰符,明确的声明该函数:
private func someFunction() -> (SomeInternalClass, SomePrivateClass) { // 函数实现 {}
将该函数申明为 public 或 internal,或者使用默认的访问级别 internal 都是错误的,因为如果这样你就无法访问 private 级别的返回值。
枚举中成员的访问级别继承自该枚举,你不能为枚举中的成员单独申明不同的访问级别。
比如下面的实例,枚举 Student 被明确的申明为 public 级别,那么它的成员 Name,Mark 的访问级别同样也是 public:
public enum Student { case Name(String) case Mark(Int,Int,Int) {} var studDetails = Student.Name("Swift") var studMarks = Student.Mark(98,97,95) switch studMarks { case .Name(let studName): print("学生名: \(studName).") case .Mark(let Mark1, let Mark2, let Mark3): اطبع("نسبة النجاح: (Mark1),(Mark2),(Mark3)") {}
نتيجة تنفيذ البرنامج أعلاه هي:
نسبة النجاح: 98,97,95
لا يمكن أن يكون مستوى الوصول للفرع أعلى من مستوى الأب. على سبيل المثال، إذا كان مستوى الوصول للأب هو internal، فإن مستوى الوصول للفرع لا يمكن أن يتم تعريفه كpublic.
public class SuperClass { fileprivate func show() { اطبع("مستوى أعلى") {} {} // مستوى الوصول لا يمكن أن يكون أعلى من مستوى الأب internal > public internal class SubClass: SuperClass { override internal func show() { اطبع("فرع") {} {} let sup = SuperClass() sup.show() let sub = SubClass() sub.show()
نتيجة تنفيذ البرنامج أعلاه هي:
مستوى أعلى فرع
لا يمكن أن يكون مستوى الوصول للثوابت والمتغيرات والخصائص أعلى من نوعها.
على سبيل المثال، إذا قمت بتعريف خاصية مستوى الوصول public، ولكن نوعها هو private، فإن هذا غير مسموح به من قبل محرر الكود.
على نفس المنوال، لا يمكن أن يكون مستوى الوصول للسحابة أعلى من نوع نوعها أو نوع العائد.
على سبيل المثال، إذا كان نوع تعريف الثابت أو المتغير أو الخاصية أو اسم المفتاح هو مستوى الوصول private، فإنه يجب التأكيد على إعلان مستوى الوصول كprivate:
private var privateInstance = SomePrivateClass()
مستوى الوصول للمدخلات والخروجات للثوابت والمتغيرات والخصائص وأسماء المفاتيح يرث من مستوى الوصول للمكونات التي تنتمي إليها.
مستوى الوصول للمدخلات يمكن أن يكون أقل من مستوى الوصول للخروجات، مما يتيح التحكم في حقوق الوصول للقراءة والكتابة على المتغيرات والخصائص أو أسماء المفاتيح.
class Samplepgm { fileprivate var counter: Int = 0{ willSet(newTotal){ اطبع("مستوى العداد: (newTotal)") {} didSet{ إذا كان (counter > oldValue) { اطبع("إضافة كمية جديدة (counter - oldValue)") {} {} {} {} let NewCounter = Samplepgm() NewCounter.counter = 100 NewCounter.counter = 800
مستوى الوصول لـ counter هو fileprivate، يمكن الوصول إليه داخل الملف.
نتيجة تنفيذ البرنامج أعلاه هي:
حساب التكرار: 100 زيادة الكمية 100 حساب التكرار: 800 زيادة الكمية 700
يمكننا تحديد مستوى الوصول للطريقة الافتراضية للتحميل المحدد، ولكن لا يمكن أن يكون أعلى من مستوى الوصول للنوع الذي ينتمي إليه. لكن هذا استثناء للحافز المطلوب، الذي يجب أن يكون مستوى الوصول نفسه لمستوى الوصول للنوع.
مستوى الوصول لمعاملات الطريقة الافتراضية للتحميل لا يمكن أن يكون أقل من مستوى الوصول للطريقة الافتراضية للتحميل.
يقدم Swift بنية واجهة للتحميل المحدد، وهي تستخدم لتقديم عمليات الافتراضية لجميع الخصائص، ولكن لا تقدم قيمًا محددة.
مستوى الوصول للطريقة الافتراضية للتحميل معين مع مستوى الوصول للنوع.
استخدم كلمة المفتاح required قبل طريقة init() في كل فرع قبلها.
class classA { required init() { var a = 10 print(a) {} {} class classB: classA { required init() { var b = 30 print(b) {} {} let res = classA() let show = classB()
نتيجة تنفيذ البرنامج أعلاه هي:
10 30 10
إذا كنت ترغب في تحديد مستوى الوصول لبروتوكول بوضوح، فإنه يجب عليك التأكد من أن البروتوكول يستخدم فقط في نطاق الوصول الذي قمت بتحديده.
إذا قمت بتعريف بروتوكول متاح عام، فإن الدوال الضرورية التي يقدمها هذا البروتوكول ستكون متاحة عامًا أيضًا. هذا يختلف عن أنواع أخرى مثل أنواع متاحة عامًا أخرى، أعضاؤها متاحة للوصول الداخلي.
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) {} // يتطلب فقط معاملًا واحدًا للطريقة المريحة 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)")
نتيجة تنفيذ البرنامج أعلاه هي:
res is: 20 res is: 30 res is: 50
يمكنك في حالة السماح بتمديد أنواع مثل الفئات أو الأشكال أو المجموعات. يجب أن يكون عضو التمديد متوافقًا مع مستوى الوصول للعضو الأصلي. على سبيل المثال، إذا تم تمديد نوع عام، فإن العضو الجديد يجب أن يكون له نفس مستوى الوصول الافتراضي للعضو.
أو، يمكنك تحديد بوضوح مستوى الوصول للتمديد (مثل استخدام private extension) للجميع في التمديد هذا جديد مستوى الوصول الافتراضي للعضو. يمكن أن تغطي هذه المستوى الوصول الافتراضي المستوى الوصول المحدد لكل عضو.
يأخذ مستوى الوصول للنوع الجماعي أو الدالة الجماعية مستوى الوصول الأدنى بين النوع الجماعي نفسه والدالة الجماعية والمعدلات الجماعية.
public struct TOS<T> { var items = [T]() private mutating func push(item: T) { items.append(item) {} mutating func pop() -> T { return items.removeLast() {} {} var tos = TOS<String>() tos.push("Swift") print(tos.items) tos.push("الأنواع المجردة") print(tos.items) tos.push("معدل نوع") print(tos.items) tos.push("اسم معدل نوع") print(tos.items) let deletetos = tos.pop()
نتيجة تنفيذ البرنامج أعلاه هي:
["Swift"] ["Swift", "الأنواع المجردة"] ["Swift", "أجسام", "معدلات نوع"] ["Swift", "أجسام", "معدلات نوع", "اسم معدل نوع"]
أي نوع اسم نوع تعده سيتم اعتباره نوعًا مختلفًا، مما يسهل التحكم في الوصول. لا يمكن أن تكون دقة اسم النوع أعلى من دقة النوع الأصلي.
على سبيل المثال، يمكن تعيين اسم نوع مستوى خصوصية عالي إلى نوع يمكنه أن يكون عامًا أو داخليًا أو خاصًا، ولكن يمكن تعيين اسم نوع مستوى عام فقط إلى نوع مستوى عام، وليس إلى نوع داخلي أو خاص.
ملاحظة: تنطبق هذه القاعدة أيضًا على تسمية أسماء别名 للأنواع لضمان تطابق البروتوكول.
public protocol Container { typealias ItemType mutating func append(item: ItemType) var count: Int { get } subscript(i: Int) -> ItemType { get } {} struct Stack<T>: Container { //تنفيذ Stack<T> الأصلي var items = [T]() mutating func push(item: T) { items.append(item) {} mutating func pop() -> T { return items.removeLast() {} //التزام البروتوكول الحاوي mutating func append(item: T) { self.push(item) {} var count: Int { return items.count {} subscript(i: Int) -> T { return items[i] {} {} func allItemsMatch< C1: Container, C2: Container حيث C1.ItemType == C2.ItemType, C1.ItemType: Equatable> (someContainer: C1, anotherContainer: C2) -> Bool { //تحقق من أن كلا الحاويتين تحتوي على نفس عدد العناصر إذا كان someContainer.count != anotherContainer.count { return false {} //تحقق من كل زوج من العناصر لمعرفة ما إذا كانت متطابقة for i in 0..<someContainer.count { if someContainer[i] != anotherContainer[i] { return false {} {} // جميع العناصر تطابق، لذا قم بإرجاع true return true {} var tos = Stack<String>() tos.push("Swift") print(tos.items) tos.push("الأنواع المجردة") print(tos.items) tos.push("جملة Where") print(tos.items) var eos = ["Swift", "الأنواع المجردة", "جملة Where"] print(eos)
نتيجة تنفيذ البرنامج أعلاه هي:
["Swift"] ["Swift", "الأنواع المجردة"] ["Swift", "الأنواع المجردة", "جملة Where"] ["Swift", "الأنواع المجردة", "جملة Where"]