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

التحقق من المساواة

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

لقد رأيت كيف يتحكم __tostring في كيفية عرض الكائن لنفسه. دالة ميتا (metamethod) مفيدة أخرى هي __eq، والتي تحدد متى يجب اعتبار كائنين متساويين باستخدام عامل ==.

بشكل افتراضي، مقارنة جدولين باستخدام == تتحقق مما إذا كانا نفس الجدول تمامًا في الذاكرة. كائنان منفصلان ببيانات متطابقة سيُرجعان false:

local user1 = {id = 101, name = "Alice"}
local user2 = {id = 101, name = "Alice"}
print(user1 == user2)  -- المخرجات: false (جداول مختلفة)

باستخدام __eq، يمكنك تعريف منطق المساواة الخاص بك. في الـ class، تقوم بإضافته تماماً مثل __tostring — كدالة في جدول الـ class. لكي تعمل المساواة، يجب أن يتشارك كلا الكائنين نفس الـ metatable:

local User = {}
User.__index = User

function User:new(id, name)
    local instance = {}
    setmetatable(instance, self)
    instance.id = id
    instance.name = name
    return instance
end

function User:__eq(other)
    return self.id == other.id
end

الآن، يُعتبر كائنا User متساويين إذا كانا يتشاركان نفس الـ ID، بغض النظر عن الحقول الأخرى:

local u1 = User:new(101, "Alice")
local u2 = User:new(101, "Bob")
local u3 = User:new(202, "Alice")

print(u1 == u2)  -- النتيجة: true (نفس المعرف)
print(u1 == u3)  -- النتيجة: false (معرفات مختلفة)

هذا النمط ذو قيمة عندما تمثل الكائنات كيانات من العالم الحقيقي بمعرفات فريدة - مقارنة سجلات قاعدة البيانات، أو كيانات الألعاب، أو أي كائنات تكون فيها الهوية أكثر أهمية من موقعها في الذاكرة.

challenge icon

التحدي

سهل

لنقم ببناء فئة Product يمكنها تحديد ما إذا كان منتجان هما نفس العنصر — حتى عندما يتم تخزينهما في جداول مختلفة تماماً! في أنظمة التجزئة، غالباً ما يكون للمنتجات رموز SKU فريدة (وحدات حفظ المخزون)، ويجب اعتبار منتجين متساويين إذا كانا يشتركان في نفس SKU، بغض النظر عن التفاصيل الأخرى مثل تغيرات الأسعار.

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

  • Product.lua: قم بتعريف فئة Product الخاصة بك باستخدام نمط النموذج الأولي (prototype pattern) القياسي. يجب أن يخزن كل منتج sku (المعرف الفريد) و name. قم بتنفيذ الطريقة الوصفية __eq بحيث يعتبر منتجان متساويين عندما يكون لهما نفس SKU — الاسم لا يهم في عملية المقارنة.
  • main.lua: استدعِ وحدة Product الخاصة بك وقم بإنشاء عدة مثيلات للمنتج. قارن بينها باستخدام عامل التشغيل == لرؤية منطق المساواة المخصص الخاص بك قيد التنفيذ.

يجب أن تتضمن فئة Product الخاصة بك ما يلي:

  • منشئ :new(sku, name)
  • طريقة :getInfo() تعيد سلسلة نصية بالتنسيق التالي: [sku]: [name]
  • الطريقة الوصفية __eq التي تقارن المنتجات من خلال SKU الخاص بها

ستتلقى ستة مدخلات:

  1. SKU للمنتج الأول
  2. الاسم للمنتج الأول
  3. SKU للمنتج الثاني
  4. الاسم للمنتج الثاني
  5. SKU للمنتج الثالث
  6. الاسم للمنتج الثالث

في ملفك الرئيسي، قم بإنشاء ثلاثة منتجات باستخدام المدخلات المقدمة، ثم اطبع:

  1. المعلومات الخاصة بكل منتج (ثلاثة أسطر)
  2. نتيجة مقارنة المنتج 1 مع المنتج 2
  3. نتيجة مقارنة المنتج 1 مع المنتج 3

على سبيل المثال، إذا كانت المدخلات هي ABC123، و Wireless Mouse، و ABC123، و Mouse (Updated)، و XYZ789، و Keyboard، فيجب أن يكون المخرج:

ABC123: Wireless Mouse
ABC123: Mouse (Updated)
XYZ789: Keyboard
true
false

لاحظ كيف أن أول منتجين متساويان (نفس SKU) على الرغم من اختلاف أسمائهما — وهذا هو بالضبط كيف تتبع أنظمة المخزون الحقيقية المنتجات من خلال تغييرات الأسماء والتحديثات!

ورقة مرجعية

يحدد التابع الوهمي (metamethod) ‏__eq منطق مساواة مخصص للكائنات باستخدام عامل التشغيل ==.

بشكل افتراضي، تتحقق مقارنة جدولين مما إذا كانا نفس الجدول في الذاكرة:

local user1 = {id = 101, name = "Alice"}
local user2 = {id = 101, name = "Alice"}
print(user1 == user2)  -- Output: false (جداول مختلفة)

لتعريف مساواة مخصصة، أضف __eq كدالة في جدول الفئة (class table). يجب أن يتشارك كلا الكائنين نفس الجدول الوهمي (metatable):

local User = {}
User.__index = User

function User:new(id, name)
    local instance = {}
    setmetatable(instance, self)
    instance.id = id
    instance.name = name
    return instance
end

function User:__eq(other)
    return self.id == other.id
end

الآن تصبح الكائنات متساوية بناءً على منطقك المخصص:

local u1 = User:new(101, "Alice")
local u2 = User:new(101, "Bob")
local u3 = User:new(202, "Alice")

print(u1 == u2)  -- Output: true (نفس المعرف ID)
print(u1 == u3)  -- Output: false (معرفات IDs مختلفة)

جرّب بنفسك

-- استدعاء وحدة المنتج (Product)
local Product = require('Product')

-- قراءة المدخلات
local sku1 = io.read()
local name1 = io.read()
local sku2 = io.read()
local name2 = io.read()
local sku3 = io.read()
local name3 = io.read()

-- TODO: إنشاء ثلاثة كائنات (instances) من المنتج باستخدام المدخلات

-- TODO: طباعة المعلومات لكل منتج (ثلاثة أسطر)

-- TODO: طباعة نتيجة مقارنة المنتج الأول مع المنتج الثاني

-- TODO: طباعة نتيجة مقارنة المنتج الأول مع المنتج الثالث
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming