0Pricing
Lua Academy · درس

الفئات عبر جداول البيانات الوصفية

حاكِ الفئات باستخدام الجداول و__index للبحث عن الأساليب

الفئات عبر جداول البيانات الوصفية درس مجاني في Lua Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Lua Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Lua Academy 4 دروس في المجموع.

نمط جدول الفئة

في Lua، «الفئة» مجرد جدول يخزن الأساليب. أما المثيلات فهي جداول تشير فيها __index في جدولها الفوقي إلى جدول الفئة. ويتيح ذلك الوصول إلى جميع الأساليب من المثيلات عبر سلسلة البحث.

local Animal = {}
Animal.__index = Animal

function Animal.new(name, sound)
  return setmetatable({name=name, sound=sound}, Animal)
end

function Animal:speak()
  print(self.name .. " says " .. self.sound)
end

local dog = Animal.new("Rex","Woof")
dog:speak()  -- Rex says Woof

يشير __index إلى الفئة

يعني ضبط ClassName.__index = ClassName «البحث عن المفاتيح المفقودة في جدول الفئة». عند استدعاء أسلوب مثيلة، لا تجده Lua في المثيلة، فتفحص الجدول الفوقي (__index)، وتعثر على الفئة، ثم تبحث عن الأسلوب فيها.

local Point = {}
Point.__index = Point

Point.type = "2D Point"

function Point.new(x,y)
  return setmetatable({x=x,y=y}, Point)
end

function Point:magnitude()
  return math.sqrt(self.x^2 + self.y^2)
end

local p = Point.new(3,4)
print(p:magnitude())   -- 5.0
print(p.type)          -- 2D Point (from class)

نمط المُنشئ

الدالة new() هي المُنشئ: تنشئ جدولًا يحوي بيانات المثيلة، ثم تعيده مغلفًا بجدول فوقي يشير إلى الفئة. وهذه هي الطريقة القياسية لإنشاء الكائنات في Lua.

local Circle = {}
Circle.__index = Circle

function Circle.new(cx, cy, radius)
  assert(radius > 0, "radius must be positive")
  return setmetatable({cx=cx, cy=cy, r=radius}, Circle)
end

function Circle:area()
  return math.pi * self.r^2
end

function Circle:perimeter()
  return 2 * math.pi * self.r
end

local c = Circle.new(0, 0, 5)
print(string.format("Area: %.2f", c:area()))

صياغة الأسلوب مقابل الدالة

‏obj:method() هي صياغة مختصرة لـ obj.method(obj). عرّف الأساليب باستخدام صياغة النقطتين (function Cls:method()) للحصول على self ضمنيًا. واستدعِ الأسلوب باستخدام النقطتين لتمرير المثيلة. ويؤدي الخلط بين النقطة والنقطتين إلى أخطاء دقيقة.

local Dog = {}
Dog.__index = Dog

-- Define with colon: self is implicit
function Dog:bark(times)
  for i = 1, (times or 1) do
    print(self.name .. ": Woof!")
  end
end

function Dog.new(name)
  return setmetatable({name=name}, Dog)
end

local d = Dog.new("Buddy")
d:bark(2)        -- Buddy: Woof! (x2)
-- Dog.bark(d,1) -- same thing, explicit self

الحقول على مستوى الفئة مقابل مستوى المثيلة

الحقول الموجودة في جدول الفئة مشتركة بين جميع المثيلات (متغيرات الفئة). أما الحقول الموجودة في جدول المثيلة فهي خاصة بكل مثيلة. ويمكن للمثيلة حجب حقل من الفئة بإنشاء حقل خاص بها يحمل الاسم نفسه.

local Entity = {}
Entity.__index = Entity
Entity.count = 0    -- class-level counter

function Entity.new(name)
  Entity.count = Entity.count + 1
  return setmetatable({name=name, id=Entity.count}, Entity)
end

local a = Entity.new("alpha")
local b = Entity.new("beta")
local c = Entity.new("gamma")

print(Entity.count)  -- 3
print(a.id, b.id, c.id)  -- 1  2  3

tostring للفئات

أضف __tostring إلى جدول الفئة للحصول على مخرجات طباعة سهلة القراءة. وبما أن الجدول الفوقي للمثيلة هو الفئة، وأن الفئة تحتوي على __tostring، فستستخدم جميع المثيلات هذا الأسلوب تلقائيًا.

local Vec2 = {}
Vec2.__index = Vec2
Vec2.__tostring = function(v)
  return string.format("Vec2(%g, %g)", v.x, v.y)
end

function Vec2.new(x,y)
  return setmetatable({x=x,y=y}, Vec2)
end

function Vec2.__add(a, b)
  return Vec2.new(a.x+b.x, a.y+b.y)
end

local v1 = Vec2.new(1,2)
local v2 = Vec2.new(3,4)
print(v1+v2)   -- Vec2(4, 6)

التحقق من نوع المثيلة

تحقّق مما إذا كان كائن ما مثيلةً لفئة، وذلك بمقارنة جدوله الفوقي بجدول الفئة. وهذا هو المكافئ في Lua لـ instanceof.

local Dog = {}
Dog.__index = Dog

function Dog.new(name)
  return setmetatable({name=name}, Dog)
end

local function isDog(obj)
  return getmetatable(obj) == Dog
end

local d = Dog.new("Rex")
local t = {}
print(isDog(d))  -- true
print(isDog(t))  -- false

الأساليب الخاصة

الأساليب الخاصة هي دوال محلية في ملف الوحدة. ولا يمكن استدعاؤها من خارج الوحدة، لكنها متاحة داخل أساليب الوحدة العامة بصفتها قيمًا مرفوعة.

local Account = {}
Account.__index = Account

-- Private helper
local function validate(amount)
  return type(amount)=="number" and amount > 0
end

function Account.new(balance)
  return setmetatable({balance=balance or 0}, Account)
end

function Account:deposit(amount)
  assert(validate(amount), "invalid amount")
  self.balance = self.balance + amount
end

function Account:getBalance() return self.balance end

مقارنة الفئات

أعد تعريف __eq و__lt لتنفيذ المساواة والترتيب المخصصين. ولا تستدعي Lua __eq للجداول إلا عندما يشترك المعاملان في الجدول الفوقي نفسه.

local Temp = {}
Temp.__index = Temp
Temp.__eq = function(a,b) return a.celsius == b.celsius end
Temp.__lt = function(a,b) return a.celsius < b.celsius end
Temp.__tostring = function(t)
  return t.celsius.."°C"
end

function Temp.new(c)
  return setmetatable({celsius=c}, Temp)
end

local t1 = Temp.new(100)
local t2 = Temp.new(0)
print(t1 == Temp.new(100))  -- true
print(t2 < t1)              -- true

فئات متعددة

كل فئة جدول مستقل له جدوله الفوقي الخاص. وتملك الكائنات المنتمية إلى فئات مختلفة جداول فوقية مختلفة. وهذا هو الأساس لنظام البرمجة كائنية التوجه متعدد الفئات في Lua.

local Cat = {}
Cat.__index = Cat

function Cat.new(name) return setmetatable({name=name,lives=9},Cat) end
function Cat:loseLife() self.lives=self.lives-1; return self.lives end

local Dog2 = {}
Dog2.__index = Dog2
function Dog2.new(name) return setmetatable({name=name,tricks={}},Dog2) end
function Dog2:learn(t) self.tricks[#self.tricks+1]=t end

local c = Cat.new("Whiskers")
local d = Dog2.new("Buddy")
d:learn("sit"); d:learn("stay")
print(c:loseLife(), #d.tricks)  -- 8  2

اختبار سريع

لماذا نضبط ClassName.__index = ClassName؟

مراجعة: الفئات عبر الجداول الفوقية

الملخص:

  • الفئة = جدول + __index = self
  • المُنشئ: function Cls.new(...) return setmetatable({}, Cls) end
  • الأساليب: تُعرَّف في جدول الفئة وتُستدعى باستخدام صياغة النقطتين
  • حقول الفئة مقابل حقول المثيلة: حقول الفئة مشتركة، وحقول المثيلة خاصة بكل كائن
  • التحقق من النوع: getmetatable(obj) == Cls

الأسئلة الشائعة

هل درس «الفئات عبر جداول البيانات الوصفية» مجاني؟

نعم — نص درس «الفئات عبر جداول البيانات الوصفية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Lua Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Lua Academy 4 دروس في المجموع.

ماذا ستتعلم في «الفئات عبر جداول البيانات الوصفية»؟

حاكِ الفئات باستخدام الجداول و__index للبحث عن الأساليب تتمرن على Lua Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Lua Academy؟

لا تُشترط خبرة سابقة. Lua Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «الفئات عبر جداول البيانات الوصفية»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Lua Academy هذا؟

نعم. كل درس في Lua Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الفئات عبر جداول البيانات الوصفية
  2. المنشئات وnew()
  3. أساليب النسخ وself
  4. التغليف باستخدام الإغلاقات
← العودة إلى Lua Academy