نصيحة سريعة: المتعددات في Swift |
تعد المتعددات نمط تصميم شائع مستخدم في عدة لغات برمجة. في حين أنك لربما تعرف عن المتعددات في C وفي Objective-C ، فإن تطبيق Swift للمتعددات يعتبر أكثر فعالية ومرونة بشكل ملحوظ. في هذه النصيحة السريعة، ستتعلم ما هو الشيء المميز بالمتعددات في Swift ، كيفية إستخدامهم في مشاريعك، وما هو الشيء الذي يجعلهم فعالين.
1. ما هي المتعددات ؟
لا تعد المتعددات شيئاً جديداً وليست حكراً لدى Swift فقط. ولكن إذا كنت ممن لديه معرفة بالمتعددات في C ، فإنك ستحب المتعددات الفعالة في Swift.إذا كنت ممن لا يعرف أي شيء عن enums أو المتعددات، فمن الممكن أنك لا تعرف ماذا يمكنهم أن يفعلوا. المتعددات في Swift هم عبارة عن أنواع من الصنف الأول تقوم بتعريف قائمة من القيم المحتملة لهذا النوع.
وقد تشكل حالات محتملة من اتصال الشبكة مثالاً ممكناً. يمكن أن تكون الحالات المحتملة:
- غير متصل
- جاري الاتصال
- متصل
ويمكن إضافة حالة رابعة لهذا المثال وهي غير معروف. تذكر هذا المثال ودعنا نرى كيفية تعرف وتطبيق المتعددات.
الأساسيات
وكما قلت تعد المتعددات أنواعاً من الصنف الأول في Swift يشبه تعريف المتعددات تعريف الصنف أو تعريف البنية. في المثال أسفلاً، سنقوم بتعريف متعددات ConnectionState.enum ConnectionState {}
يسبق اسم المتعددات بـ: كلمة enum الأساسية ويتبع بـزوج من الأقواس المعوجة كما في المثال. ستقوم متعددات ConnectionState بتعريف حالات ممكنة لاتصال الشبكة. لتعريف هذه الحالات سنضيف أعضاء ذات قيمة أو أعضاء لتعريف المتعددات. دائماً ما يبدأ تعريف العضو ذات القيمة بـكلمة حالة الأساسية.
enum ConnectionState {case Unknowncase Disconnectedcase Connectingcase Connected}
في كل من C و Objective-C ، سيبدو المتعدد مختلفاً قليلاً كما هو موضح في المقال أسفلاً. ستتوافق كل قيمة من قيم المتعددات مع رقم، على سبيل المثال، ConnectionStateUnknown تساوي 0 ، ConnectionStateDisconnected تساوي 1 ، .. إلخ.
typedef enum : NSUInteger {ConnectionStateUnknown,ConnectionStateDisconnected,ConnectionStateConnecting,ConnectionStateConnected} ConnectionState;
هذا لا ينطبق على Swift . لا يتوافق أعضاء المتعددات بشكل أوتوماتيكي مع قيمة رقمية. تعد أعضاء متعددات ConnectionState قيماً بحد ذاتها وهي من نوع ConnectionState . وهذا ما يجعل العمل مع المتعددات أكثر سهولة و وضوحاً.
القيم الخام
من الممكن تحديد قيم أعضاء المتعددات بوضوح. في المثال التالي، هنالك متعددات ConnectionState ذات قيمة خام من نوع Int . يتم تعيين قيمة خام لكل عضو، متوافقاً مع رقم.enum ConnectionState: Int {case Unknown = -1case Disconnected = 0case Connecting = 1case Connected = 2}
enum ConnectionState: Int {case Unknown = -1case Disconnectedcase Connectingcase Connected}
2. العمل مع المتعددات
Initialization (البدأ)
يعتبر استخدام متعددات ConnectionState مشابهاً لأي نوع آخر في Swift في المثال التالي، سنعلن عن متغير، connectionState ، ونضع ConnectionState.Connecting قيمة له.var connectionState = ConnectionState.Connecting
تعتبر ConnectionState.Connecting قيمة لـ: connectionState. ويعد المتغير من نوع ConnectionState.
يعد استدلال نوع Swift مريح جداً عند العمل مع المتعددات. لأننا قلنا أن connectionState هي عبارة عن نوع ConnectionState ، فإنه بإمكاننا الآن أن نعين قيمة جديدة من خلال استخدام تركيبة كود النقطة للمتعددات.
connectionState = .Connected
التحكم بالتدفق
يعتبر استخدام المتعددات في عبارة إذا أو في تقرير Swift بسيطاً جداً. تذكر أنه يجب على تقارير Swift أن تكون كاملة. أضف حالة افتراضية (default) إذا استلزم الأمر.enum ConnectionState {
case Unknown
case Disconnected
case Connecting
case Connected
}
var connectionState = ConnectionState.Connecting
connectionState = .Connected
switch connectionState {
case .Disconnected:
println("Disconnected")
case .Connecting:
println("Connecting")
case .Connected:
println("Connected")
default:
println("Unknown State")
}
يعرض المثال التالي كيفية استخدام ConnectionState enum . ويوضح أيضاً كيفية الولوج إلى القيمة المرتبطة بعضو enum . تقوم canConnect function بقبول نموذج ConnectionState وتعيده كـ: Bool.
func canConnect(connectionState: ConnectionState) -> Bool {
var result = false
switch connectionState {
case .Connected(let port):
if port == 3000 {
result = true
}
default:
result = false
}
return result
}
let state = ConnectionState.Connected(3000)
if canConnect(state) {
// ...
}
عود canConnect function صحيحة فقط إذا كان نموذج ConnectionState الذي تم تمريره إلى function مساوياً له. يعد المتصل والقيمة المرتبطة به Int مساوياً لـ: 3000 لاحظ أن القيمة المرتبطة بالعضو Connected ظاهرة بتقرير Swift كمنفذ مسمى دائم، الذي يمكن حينئذ استخدامه في الحالة المتوافقة.
3. القيم المرتبطة
تعد القيم المرتبطة ميزة أخرى مشوقة في Swift enum يمكن لكل عضو من enum أن يكون لديه قيمته الخاصة المرتبطة به. تعد القيم المرتبطة مرنة جداً. مثلاً لا يجب على القيم المرتبطة التابعة لأعضاء مختلفين من نفس enum أن يكونوا من نفس النوع. للفهم أكثر مفهوم القيم المرتبطة، ألق نظرة على المثال التالي:enum ConnectionState {case Unknowncase Disconnectedcase Connecting(Int, Double)case Connected(Int)}
لا يجب على الأعضاء Unknown و Disconnected أن يكون لديهم قيم مرتبطة. ولكن لدى عضو Connecting قيمة من نوع Int) Double)، وهي تحدد رقم المنفذ وفترة إنتهاء مدة الاتصال. لدى عضو Connected قيمة مرتبطة من نوع Int ، وهي تحدد رقم المنفذ.
من الضروري فهمه إن القيمة المرتبطة تتصل أو ترتبط بعضو من المتعددات. وتبقى قيمة العضو ثابتة وغير متغيرة. يوضح المثال التالي كيفية إبتكار نموذج ConnectionState مع قيمة مرتبطة.
var connectionState = ConnectionState.Connecting(3000, 30.0)
4. الطرق وأنواع القيم
الطرق
تعتبر المتعددات فعالة جداً في Swift يمكن للمتعددات حتى أن تعرف الطرق، كـ: initializer من أجل إختيار عضو افتراضي (default) إذا لم يكن أيها محدداً.enum ConnectionState {case Unknowncase Disconnectedcase Connecting(Int, Double)case Connected(Int)init () {self = .Unknown}}var connectionState = ConnectionState() // .Unknown
في هذا المثال، سنبدأ بنموذج من متعددات ConnectionState من دون تحديد قيمة لها بشكل واضح. ولكن في initializer المتعددات سنضع النموذج Unknown. وتكون النتيجة أن متغير connectionState مساوياً لـ: ConnectionState.Unknown.
أنواع القيم
تعد البنى كالمتعددات التي هي عبارة أنواع قيمة مما يعني أن المتعدد لن يتم تمريره عن طريق مرجع، كما يحدث في نماذج الصنف، ولكن عن طريق القيم. سيوضح ذلك المثال التالي.var connectionState1 = ConnectionState()
var connectionState2 = connectionState1
connectionState1 = .Connected(1000)
println(connectionState1) // .Connected(1000)
println(connectionState2) // .Unknown
على الرغم من أننا نعين connectionState1 لـ: connectionState2 ، فإن قيم connectionState1 و connectionState2 تصبح مختلفة في نهاية المثال.
عندما نقوم بتعيين connectionState1 لـ: connectionState2 ، فإن Swift يبتكر نسخة عن connectionState1 ويقوم بتعيينها لـ: connectionState2 . وبكلمات أخرى، فإن كلا من connectionState1 و connectionState2 ترجع لنموذجين مختلفين من ConnectionState.
ليست هناك تعليقات: