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

متغيرات النسخة

جزء من قسم Object Oriented Programming في رحلة Lua على Coddy — الدرس 12 من 70.

مرحباً بك في فصل جديد يركز على كيفية إدارة الكائنات لبياناتها الداخلية. لقد تعلمت كيفية إنشاء الفئات (classes) والنماذج (instances) — والآن حان الوقت لاستكشاف كيفية قيام كل نموذج بتخزين وإدارة حالته الفريدة.

متغيرات النسخة (Instance variables) هي حقول تنتمي حصرياً لكائن واحد. عندما تقوم بتعيين قيمة لـ self.something داخل دالة (method) أو منشئ (constructor)، فإن تلك البيانات تعيش فقط في تلك النسخة المحددة. الكائنات الأخرى من نفس الفئة (class) لديها نسخها المنفصلة الخاصة بها.

يصبح هذا مهماً بشكل خاص عند تخزين بيانات معقدة مثل الجداول. فكر في نظام مخزون حيث يحمل كل شخصية عناصر مختلفة:

local Inventory = {}
Inventory.__index = Inventory

function Inventory:new()
    local instance = {}
    setmetatable(instance, self)
    instance.items = {}  -- تحصل كل نسخة على جدول فارغ خاص بها
    return instance
end

function Inventory:addItem(item)
    table.insert(self.items, item)
end

السطر الأساسي هو instance.items = {}. من خلال إنشاء جدول فارغ جديد داخل المنشئ (constructor)، يحصل كل كائن مخزون (inventory object) على قائمته المستقلة الخاصة به. إذا قمت بدلاً من ذلك بتعريف items في جدول الفئة (class table) نفسه، فإن جميع النسخ (instances) ستتشارك نفس الجدول عن طريق الخطأ - فإضافة سيف لشخصية واحدة سيمنحه للجميع!

local bag1 = Inventory:new()
local bag2 = Inventory:new()

bag1:addItem("Sword")
bag2:addItem("Potion")

print(#bag1.items)  -- المخرجات: 1
print(#bag2.items)  -- المخرجات: 1

كل مخزون يحتفظ بمجموعته الخاصة. ينطبق هذا النمط كلما احتاج مثيل (instance) إلى تتبع بيانات تتغير بشكل مستقل—القوائم، أو العدادات، أو أي حالة متغيرة (mutable state) فريدة لهذا الكائن.

challenge icon

التحدي

سهل

لنقم ببناء نظام ShoppingCart حيث تحتفظ كل عربة تسوق بقائمة منتجات منفصلة خاصة بها. سيوضح هذا كيف تحافظ متغيرات النسخة (instance variables) على عزل البيانات بين الكائنات - فإضافة عناصر إلى عربة واحدة لن تؤثر على الأخرى!

ستقوم بتنظيم الكود الخاص بك عبر ملفين:

  • ShoppingCart.lua: قم بتعريف فئة ShoppingCart حيث تمتلك كل نسخة جدول products الخاص بها. قم بتضمين:
    • منشئ :new() يقوم بتهيئة قائمة منتجات فارغة لكل عربة.
    • طريقة :addProduct(productName) تضيف منتجاً إلى قائمة هذه العربة.
    • طريقة :listProducts() تقوم بطباعة كل منتج في سطر منفصل.
  • main.lua: اطلب وحدة ShoppingCart وقم بإنشاء عربتي تسوق منفصلتين. أضف منتجات مختلفة إلى كل عربة لإثبات أنها تحتفظ بمخزونات مستقلة.

ستتلقى أربعة مدخلات:

  1. المنتج الأول لإضافته إلى العربة A
  2. المنتج الثاني لإضافته إلى العربة A
  3. المنتج الأول لإضافته إلى العربة B
  4. المنتج الثاني لإضافته إلى العربة B

في ملفك الرئيسي:

  1. قم بإنشاء عربتي تسوق: cartA و cartB
  2. أضف أول منتجين إلى cartA
  3. أضف آخر منتجين إلى cartB
  4. اطبع Cart A: ثم اسرد منتجات العربة A
  5. اطبع Cart B: ثم اسرد منتجات العربة B

على سبيل المثال، إذا كانت المدخلات هي Apple، و Bread، و Milk، و Eggs، يجب أن يكون المخرج:

Cart A:
Apple
Bread
Cart B:
Milk
Eggs

تذكر: المفتاح هو تهيئة products كجدول فارغ جديد داخل المنشئ. يضمن ذلك حصول كل نسخة من العربة على قائمتها المنفصلة بدلاً من مشاركة جدول واحد عبر جميع العربات.

ورقة مرجعية

متغيرات النسخة (Instance variables) هي حقول تنتمي حصرياً لكائن واحد. عندما تقوم بتعيين قيمة لـ self.something داخل دالة أو منشئ (constructor)، فإن تلك البيانات تعيش فقط في تلك النسخة المحددة.

لإنشاء متغيرات النسخة، قم بتهيئتها داخل المنشئ باستخدام جدول جديد لكل نسخة:

local Inventory = {}
Inventory.__index = Inventory

function Inventory:new()
    local instance = {}
    setmetatable(instance, self)
    instance.items = {}  -- Each instance gets its own empty table
    return instance
end

function Inventory:addItem(item)
    table.insert(self.items, item)
end

المفتاح هو instance.items = {}—إنشاء جدول فارغ جديد داخل المنشئ يضمن حصول كل كائن على بياناته المتميزة الخاصة به. إذا قمت بتعريف items في جدول الفئة (class table) نفسه، فستتشارك جميع النسخ نفس الجدول.

local bag1 = Inventory:new()
local bag2 = Inventory:new()

bag1:addItem("Sword")
bag2:addItem("Potion")

print(#bag1.items)  -- Output: 1
print(#bag2.items)  -- Output: 1

تحافظ كل نسخة على مجموعتها الخاصة بشكل مستقل. ينطبق هذا النمط على أي حالة متغيرة (mutable state) فريدة لكائن ما—مثل القوائم، العدادات، أو البيانات الأخرى التي تتغير لكل نسخة.

جرّب بنفسك

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

-- قراءة المدخلات
local product1 = io.read()
local product2 = io.read()
local product3 = io.read()
local product4 = io.read()

-- TODO: إنشاء عربتي تسوق: cartA و cartB

-- TODO: إضافة product1 و product2 إلى cartA

-- TODO: إضافة product3 و product4 إلى cartB

-- TODO: طباعة "Cart A:" ثم عرض قائمة منتجات cartA

-- TODO: طباعة "Cart B:" ثم عرض قائمة منتجات cartB
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming