نمط الـ Iterator
جزء من قسم البرمجة كائنية التوجه في رحلة Lua على Coddy. الدرس 64 من 70.
عندما يكون لديك مجموعة من العناصر مخزنة داخل كائن، غالبًا ما تريد المرور عليها باستخدام حلقة. تعمل حلقة for العامة في Lua مع أي دالة مُكرِّر: فهي تستدعي الدالة قبل كل تكرار، وتتوقف عندما تُرجع الدالة nil.
يمنح نمط المكرّر الكائنَ دالةً تُرجع مثل هذه الدالة. تحتفظ الدالة بموضعها في متغير محلي، لذا ينتمي الموضع إلى حلقة واحدة، لا إلى المجموعة:
local Collection = {}
Collection.__index = Collection
function Collection:new()
local obj = { items = {} }
setmetatable(obj, Collection)
return obj
end
function Collection:add(item)
table.insert(self.items, item)
end
function Collection:iter()
local index = 0
return function()
index = index + 1
return self.items[index]
end
endينشئ كل استدعاء لـ bag:iter() دالة جديدة لها index خاص بها، وتبدأ قيمته من 0. الدالة إغلاق (closure): إذ لا يزال بإمكانها استخدام index وself بعد أن يعيد iter القيمة. بعد العنصر الأخير، تكون قيمة self.items[index] هي nil، وتتوقف الحلقة:
local bag = Collection:new()
bag:add("apple")
bag:add("banana")
for item in bag:iter() do
print(item) -- apple، ثم banana
end
for item in bag:iter() do
print(item) -- apple، ثم banana مرة أخرى
endأبقِ الموضع خارج المجموعة نفسها. إذا خزّن الكائن self.index وعمل كمكرّر خاص به، فستنتهي الحلقة الأولى والمؤشر عند النهاية، لذا لن تطبع الحلقة الثانية شيئًا، كما أن الحلقة التي تتوقف مبكرًا باستخدام break ستجعل الحلقة التالية تبدأ من المنتصف.
التحدي
سهللننشئ صنف Playlist يمكنك التكرار عليه باستخدام حلقة for العامة في Lua! ستنفّذ نمط المكرّر باستخدام طريقة :iter() التي تُعيد دالة مكرّر.
ستوزّع شيفرتك على ملفين:
Playlist.lua: أنشئ صنف Playlist يخزّن الأغاني داخليًا. يحتاج صنفك إلى مُنشئ:new()يهيّئ قائمة أغاني فارغة، وإلى طريقة:addSong(title)تضيف أغنية إليها. والأهم من ذلك، أضف طريقة:iter()تُعيد دالة جديدة في كل مرة تُستدعى فيها. تحتفظ تلك الدالة بموضعها في متغيّر محلي، وتُعيد الأغنية التالية عند كل استدعاء، أوnilعندما لا تبقى أغانٍ.main.lua: استورِد وحدة Playlist وأنشئ قائمة تشغيل جديدة. أضف إليها الأغاني استنادًا إلى المدخلات التي تتلقاها، ثم استخدم حلقةforعامة علىplaylist:iter()لطباعة عنوان كل أغنية في سطر مستقل.
لأن كل استدعاء لـ :iter() يبدأ من الأغنية الأولى، يمكنك تكرار قائمة التشغيل نفسها أي عدد من المرات.
ستتلقى ثلاثة مدخلات، يمثّل كل منها عنوان أغنية لإضافتها إلى قائمة التشغيل (بالترتيب).
على سبيل المثال، إذا كانت المدخلات هي Bohemian Rhapsody وStairway to Heaven وHotel California، فينبغي أن يكون الناتج:
Bohemian Rhapsody
Stairway to Heaven
Hotel Californiaإذا كانت المدخلات هي Yesterday وImagine وLet It Be، فينبغي أن يكون الناتج:
Yesterday
Imagine
Let It Beجرّب بنفسك
-- استورد وحدة Playlist
local Playlist = require('Playlist')
-- اقرأ عناوين ثلاث أغانٍ من الإدخال
local song1 = io.read()
local song2 = io.read()
local song3 = io.read()
-- TODO: أنشئ قائمة تشغيل جديدة باستخدام Playlist:new()
-- TODO: أضف الأغاني الثلاث إلى قائمة التشغيل باستخدام :addSong()
-- TODO: استخدم حلقة for عامة للتكرار عبر playlist:iter()
-- واطبع عنوان كل أغنية في سطر مستقل
-- تلميح: for song in playlist:iter() do ... end
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
4مشروع: بنك رقمي
إعداد المشروعطريقة الإيداع7تعدد الأشكال وإعادة التعريف
إعادة تعريف الدوالاستدعاء دوال الفئة الأبDuck Typingواجهة مشتركةالتحقق من النوعمراجعة - أدوار الموظفين2نمط النموذج الأولي للفئات
مفهوم النموذج الأوليالربط باستخدام __indexالمنشئ :new()تهيئة الخصائصنسخ مستقلةملخص - مصنع السيارات5تحميل المعاملات في OOP
جمع الكائناتطرح الكائناتدمج الكائناتمقارنة الكائنات (<, >)مراجعة - رياضيات المحفظة8التغليف
اصطلاحات التسميةاستخدام Closures للخصوصيةالوصول عبر Closuresجداول للقراءة فقطمنطق التحقق من الصحةمراجعة - الخزنة الآمنة11أنماط التصميم (مبسط)
دوال المصنعجدول Singletonنمط الـ Iteratorالمراقب (المستمع)مراجعة - مصنع الـ Logger3حالة الكائن وسلوكه
متغيرات النسخةدالات الجلب (Getter Methods)دالات التعيين (Setter Methods)الخصائص المحسوبةتنسيق النصوصالتحقق من المساواةمراجعة - درجة الطالب6أساسيات الوراثة
إعداد الوراثةوراثة الـ Methodsتوسيع الـ Constructorإضافة Methods للابنالمشترك مقابل الفريدملخص - التسلسل الهرمي للأشكالتدرّب بنفسك: مترجم Lua عبر الإنترنت