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

نمط الـ Iterator

جزء من قسم البرمجة كائنية التوجه في رحلة Lua على Coddy. الدرس 64 من 70.

عندما تكون لديك مجموعة من items مخزّنة داخل كائن، فغالبًا ما تريد إجراء loop عليها. تعمل حلقة for generic في Lua بشكل رائع مع المكررات المخصّصة، ويمكنك بناء هذه الوظيفة مباشرةً داخل أصنافك.

يتيح Iterator pattern للكائن التحكم في كيفية اجتياز بياناته الداخلية. يستخدم أحد الأساليب الأنيقة __call metamethod، الذي يجعل الكائن قابلاً للاستدعاء مثل function. يُرجع كل استدعاء العنصر item التالي حتى لا يتبقى more.

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() ‏loop بشكل متكرر. عندما تُرجع __call القيمة nil (أي لا مزيد من items)، يتوقف loop. ي encapsulate هذا النمط منطق iteration داخل الكائن نفسه، مما يمنحك تحكمًا كاملًا في كيفية الوصول إلى items وترتيب الوصول إليها.

challenge icon

التحدي

سهل

لنُنشئ class باسم Playlist يمكنك إجراء iteration عليه باستخدام حلقة for generic في Lua! ستنفّذ نمط Iterator باستخدام metamethod باسم __call، مما يتيح اجتياز قائمة التشغيل أغنيةً تلو الأخرى.

ستنظّم الشيفرة عبر ملفين:

  • Playlist.lua: أنشئ class باسم Playlist يخزّن الأغاني داخليًا. يجب أن يحتوي class على Constructor باسم :new() يهيّئ قائمة أغاني empty ويضبط index الخاص بـ iteration على 0. أضف method باسم :addSong(title) لإضافة الأغاني إلى قائمة التشغيل. والأهم من ذلك، نفّذ metamethod باسم __call بحيث يعيد، في كل مرة يتم فيها "called" قائمة التشغيل، الأغنية التالية في القائمة (أو nil عند عدم وجود المزيد من الأغاني).
  • main.lua: استورد module Playlist وأنشئ قائمة تشغيل جديدة. أضف إليها الأغاني استنادًا إلى المدخلات التي تتلقاها، ثم استخدم حلقة for generic لإجراء iteration عبر قائمة التشغيل وطباعة عنوان كل أغنية في سطر منفصل.

تكمن روعة نمط Iterator في أن كائن 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

جرّب بنفسك

-- استورد وحدة Playlist
local Playlist = require('Playlist')

-- اقرأ ثلاثة عناوين أغاني من الإدخال
local song1 = io.read()
local song2 = io.read()
local song3 = io.read()

-- TODO: أنشئ قائمة تشغيل جديدة باستخدام Playlist:new()

-- TODO: أضف الأغاني الثلاث إلى قائمة التشغيل باستخدام :addSong()

-- TODO: استخدم حلقة for عامة للتكرار عبر قائمة التشغيل
-- واطبع عنوان كل أغنية في سطر خاص به
-- Hint: for song in playlist do ... end
quiz iconاختبر نفسك

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

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Lua عبر الإنترنت