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