Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نمط الـ 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 (لا يوجد المزيد من العناصر)، تتوقف الحلقة. يقوم هذا النمط بتغليف منطق التكرار داخل الكائن نفسه، مما يمنحك تحكماً كاملاً في كيفية - وبأي ترتيب - يتم الوصول إلى العناصر.

challenge icon

التحدي

سهل

دعنا نبني فئة 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
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming