الفئات عبر جداول البيانات الوصفية
حاكِ الفئات باستخدام الجداول و__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 3tostring للفئات
أضف __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 يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- الفئات عبر جداول البيانات الوصفية
- المنشئات وnew()
- أساليب النسخ وself
- التغليف باستخدام الإغلاقات