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

المشترك مقابل الفريد

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

عند العمل مع الوراثة، من المهم فهم أين يوجد كل جزء من البيانات. بعض السمات تكون مشتركة—تُعرّف في الفئة الأب وتكون متاحة لجميع الأبناء. والبعض الآخر فريد—يتم إنشاؤه خصيصاً في الفئة الابن أو النسخة (instance).

تأمل هذا التسلسل الهرمي:

local Animal = {}
Animal.__index = Animal
Animal.kingdom = "Animalia"  -- مشترك: مُعرّف في الفئة

function Animal:new(name)
    local obj = {name = name}  -- فريد: مخزن في كل مثيل
    setmetatable(obj, Animal)
    return obj
end
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
Dog.sound = "bark"  -- مشترك بين جميع الكلاب

function Dog:new(name, breed)
    local obj = Animal.new(Animal, name)
    obj.breed = breed  -- فريد: كل كلب له سلالته الخاصة
    setmetatable(obj, Dog)
    return obj
end

عندما تقوم بإنشاء مثيل (instance) لـ Dog، توجد بعض القيم مباشرة على الكائن (object) بينما يتم العثور على قيم أخرى من خلال سلسلة البحث (lookup chain):

local rex = Dog:new("Rex", "German Shepherd")

-- فريد لهذا المثيل (مخزن في rex)
print(rex.name)    -- "Rex"
print(rex.breed)   -- "German Shepherd"
-- مشترك (تم العثور عليه عبر البحث)
print(rex.sound)   -- "bark" (من Dog)
print(rex.kingdom) -- "Animalia" (من Animal)

التمييز الأساسي: الحقول المسندة إلى obj في المنشئات (constructors) تكون فريدة لكل مثيل، بينما الحقول المعرفة مباشرة على جداول الفئات (class tables) تتم مشاركتها عبر جميع مثيلات تلك الفئة وفئاتها الفرعية.

challenge icon

التحدي

سهل

دعنا نستكشف كيف تتدفق البيانات عبر تسلسل هرمي للوراثة من خلال بناء نظام فئات Creature و Dragon. ستكتشف بنفسك أي السمات يتم مشاركتها عبر جميع النسخ (instances) وأيها فريد لكل كائن فردي.

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

  • Creature.lua: قم بتعريف الفئة الأب (parent class) مع سمة مشتركة على مستوى الفئة world = "Fantasy Realm" تشترك فيها جميع المخلوقات. قم بتضمين منشئ :new(name) يقوم بتخزين اسم المخلوق كسمة نسخة (instance attribute).
  • Dragon.lua: قم بتعريف الفئة الابن (child class) التي ترث من Creature. أضف سمة مشتركة على مستوى الفئة element = "fire" تشترك فيها جميع التنانين. يجب أن يستدعي منشئك :new(name, color) منشئ الأب للاسم، ثم يضيف color كسمة نسخة فريدة لكل تنين.
  • main.lua: قم بإنشاء تنينين مختلفين وافحص سماتهما لتوضيح الفرق بين البيانات المشتركة والفريدة.

ستتلقى مدخلين:

  1. اسم ولون التنين الأول، مفصولين بفاصلة (على سبيل المثال، Smaug,red)
  2. اسم ولون التنين الثاني، مفصولين بفاصلة (على سبيل المثال، Draco,gold)

في ملفك الرئيسي، قم بإنشاء كلا التنينين بأسمائهما وألوانهما الخاصة. ثم اطبع المعلومات التالية بهذا الترتيب الدقيق:

  1. name الخاص بالتنين الأول
  2. color الخاص بالتنين الأول
  3. name الخاص بالتنين الثاني
  4. color الخاص بالتنين الثاني
  5. element الخاص بالتنين الأول (مشترك من فئة Dragon)
  6. element الخاص بالتنين الثاني (مشترك من فئة Dragon)
  7. world الخاص بالتنين الأول (مشترك من فئة Creature)

على سبيل المثال، إذا كانت المدخلات هي Smaug,red و Draco,gold، يجب أن يكون المخرج:

Smaug
red
Draco
gold
fire
fire
Fantasy Realm

لاحظ كيف أن name و color مختلفان لكل تنين (سمات نسخة فريدة)، بينما element و world هما نفسهما لكليهما (سمات فئة مشتركة يتم العثور عليها من خلال سلسلة البحث lookup chain).

ورقة مرجعية

في هرميات الوراثة، يمكن أن تكون السمات إما مشتركة (يتم تعريفها في جدول الفئة) أو فريدة (يتم تخزينها في النسخ الفردية).

يتم تعريف السمات المشتركة مباشرة في جداول الفئات ويتم الوصول إليها من خلال سلسلة البحث في الجدول الوصفي (metatable lookup chain):

local Animal = {}
Animal.__index = Animal
Animal.kingdom = "Animalia"  -- Shared across all Animals

يتم تعيين السمات الفريدة لكائن النسخة (obj) في الدوال الإنشائية (constructors):

function Animal:new(name)
    local obj = {name = name}  -- Unique to each instance
    setmetatable(obj, Animal)
    return obj
end

يمكن أن تمتلك الفئات الفرعية سماتها المشتركة الخاصة بها مع وراثة سمات الفئة الأب:

local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
Dog.sound = "bark"  -- Shared among all Dogs

function Dog:new(name, breed)
    local obj = Animal.new(Animal, name)  -- Call parent constructor
    obj.breed = breed  -- Add unique child attribute
    setmetatable(obj, Dog)
    return obj
end

الوصول إلى السمات:

local rex = Dog:new("Rex", "German Shepherd")

-- Unique (stored directly on rex)
print(rex.name)    -- "Rex"
print(rex.breed)   -- "German Shepherd"

-- Shared (found via metatable lookup)
print(rex.sound)   -- "bark" (from Dog class)
print(rex.kingdom) -- "Animalia" (from Animal class)

جرّب بنفسك

-- main.lua: إنشاء التنانين وتوضيح السمات المشتركة مقابل الفريدة

local Dragon = require('Dragon')

-- قراءة المدخلات للتنين الأول (الاسم، اللون)
local input1 = io.read()
-- قراءة المدخلات للتنين الثاني (الاسم، اللون)
local input2 = io.read()

-- TODO: تحليل المدخل الأول لاستخراج الاسم واللون
-- تلميح: استخدم string.match مع النمط "([^,]+),([^,]+)"

-- TODO: تحليل المدخل الثاني لاستخراج الاسم واللون

-- TODO: إنشاء التنين الأول باسمه ولونه

-- TODO: إنشاء التنين الثاني باسمه ولونه

-- TODO: اطبع ما يلي بالترتيب:
-- 1. اسم التنين الأول
-- 2. لون التنين الأول
-- 3. اسم التنين الثاني
-- 4. لون التنين الثاني
-- 5. عنصر التنين الأول (مشترك من فئة Dragon)
-- 6. عنصر التنين الثاني (مشترك من فئة Dragon)
-- 7. عالم التنين الأول (مشترك من فئة Creature)
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming