كتابة ملف وحدة
أنشئ وحدة بإرجاع جدول من الدوال من ملف .lua
كتابة ملف وحدة درس مجاني في Lua Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Lua Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Lua Academy 4 دروس في المجموع.
النمط الأساسي للوحدة
النمط القياسي للوحدات في Lua هو إنشاء جدول محلي M، ثم إضافة الدوال والقيم إليه، وإعادته في النهاية. يمثّل الجدول واجهة الوحدة العامة. أما جميع المتغيرات المحلية الأخرى في الملف فهي خاصة.
-- stringutils.lua
local M = {}
function M.trim(s)
return s:match("^%s*(.-)%s*$")
end
function M.split(s, sep)
local t = {}
for p in s:gmatch("[^"..sep.."]+") do t[#t+1]=p end
return t
end
return M
-- Usage:
-- local su = require("stringutils")
-- print(su.trim(" hello "))الحالة الخاصة
المتغيرات المعلنة باستخدام local في ملف الوحدة تكون خاصة، ولا يمكن للمستدعين الوصول إليها. ويمكن للدوال الموجودة في الوحدة الوصول إلى الحالة الخاصة باعتبارها upvalues. هذه هي آلية التغليف في Lua.
-- counter.lua
local M = {}
local count = 0 -- private state
function M.increment(n)
count = count + (n or 1)
end
function M.reset()
count = 0
end
function M.get()
return count
end
return Mوحدة مع التهيئة
تحتاج بعض الوحدات إلى التهيئة، مثل الإعدادات والاتصالات. ضعوا رمز التهيئة على مستوى الوحدة (في بداية الملف) أو داخل دالة صريحة هي M.init(). يُنفَّذ الأسلوب الأول مرة واحدة عند طلب الوحدة أول مرة، بينما يتطلب init() استدعاءً صريحًا.
-- cache.lua
local M = {}
local store = {} -- initialized at load time
local hits = 0
local misses = 0
function M.get(key)
if store[key] ~= nil then
hits = hits + 1
return store[key]
end
misses = misses + 1
return nil
end
function M.set(key, val) store[key] = val end
function M.stats() return {hits=hits, misses=misses} end
return Mوحدة مع صنف
يمكن للوحدة تصدير صنف: أي جدول يحتوي على دالة إنشاء. يحتوي جدول الوحدة المُعاد على الدالة new()، وقد يعمل أيضًا باعتباره metatable للصنف.
-- point.lua
local Point = {}
Point.__index = Point
function Point.new(x, y)
return setmetatable({x=x, y=y}, Point)
end
function Point:distance(other)
local dx, dy = self.x-other.x, self.y-other.y
return math.sqrt(dx*dx + dy*dy)
end
function Point:__tostring()
return string.format("(%g,%g)", self.x, self.y)
end
return Point
-- Usage:
-- local Point = require("point")
-- local p = Point.new(3, 4)ثوابت الوحدة
صدّروا الثوابت بإضافتها إلى جدول الوحدة. جرت العادة على كتابة الثوابت بأحرف كبيرة. وبما أن Lua لا تحتوي على const، يمكن للمستخدمين تعديلها تقنيًا، لكن تسمية الأحرف الكبيرة تشير إلى «عدم تغييرها».
-- colors.lua
local M = {}
M.RED = {r=255, g=0, b=0}
M.GREEN = {r=0, g=255, b=0}
M.BLUE = {r=0, g=0, b=255}
M.WHITE = {r=255, g=255, b=255}
M.BLACK = {r=0, g=0, b=0}
function M.toHex(c)
return string.format("#%02X%02X%02X", c.r, c.g, c.b)
end
return Mإصدارات الوحدة
أدرجوا حقل إصدار في الوحدة. يمكن للمستدعين التحقق من الإصدار لضمان التوافق. استخدموا الإصدار الدلالي (major.minor.patch).
-- mylib.lua
local M = {}
M._VERSION = "1.2.3"
M._NAME = "mylib"
M._DESCRIPTION = "My Lua library"
function M.hello(name)
return "Hello, " .. (name or "World") .. "!"
end
return M
-- Usage:
local mylib = require("mylib")
print(mylib._VERSION) -- 1.2.3
print(mylib.hello("Lua"))الوحدات الفرعية
تُقسَّم المكتبات الكبيرة إلى وحدات فرعية. قد تتطلب الوحدة الرئيسية الوحدات الفرعية وتعيد تصديرها، أو قد تُستخدم كل وحدة فرعية بشكل مستقل. نظّموا الملفات في أدلة تطابق مسار الوحدة.
-- mylib/init.lua (loaded by require("mylib"))
local M = {}
M.strings = require("mylib.strings")
M.tables = require("mylib.tables")
M.math = require("mylib.math")
M._VERSION = "2.0.0"
return M
-- Users can require the whole library:
-- local mylib = require("mylib")
-- mylib.strings.trim(...)
-- Or individual sub-modules:
-- local strs = require("mylib.strings")وحدة مع metatable
اجعلوا الوحدة قابلة للاستدعاء بمنحها metatable يحتوي على __call. يفيد ذلك الوحدات التي تكون في الأساس دوال، لكنها تحتوي أيضًا على أدوات مساعدة؛ إذ تكون العملية «الرئيسية» هي الاستدعاء، بينما تكون الأدوات حقولًا.
-- format.lua
local M = {}
setmetatable(M, {__call = function(_, fmt, ...)
return string.format(fmt, ...)
end})
function M.pad(s, width, char)
char = char or " "
return string.rep(char, math.max(0, width - #s)) .. s
end
return M
-- Usage:
-- local fmt = require("format")
-- print(fmt("%.2f", 3.14)) -- 3.14
-- print(fmt.pad("42", 5)) -- 42التحميل الكسول للوحدات الفرعية
استخدموا __index لتحميل الوحدات الفرعية بشكل كسول، أي عند الوصول إليها لأول مرة فقط. يؤدي ذلك إلى تسريع بدء التشغيل في المكتبات الكبيرة التي تحتوي على وحدات فرعية كثيرة.
-- biglib.lua
local M = {}
local submodules = {"strings", "tables", "math", "io"}
setmetatable(M, {
__index = function(t, k)
for _, name in ipairs(submodules) do
if name == k then
local mod = require("biglib." .. k)
rawset(t, k, mod)
return mod
end
end
return nil
end
})
return M
-- Loads biglib.strings only when accessed:
-- local lib = require("biglib")
-- lib.strings.trim(...)نمط اختبار الوحدة
أضيفوا دالة أو كتلة اختبار في نهاية ملف الوحدة، على أن تُنفَّذ بشكل مشروط فقط عند تشغيل الملف مباشرةً (وليس عند طلبه). يحافظ ذلك على وجود اختبارات الوحدة إلى جانب الشفرة الخاصة بها.
-- utils.lua
local M = {}
function M.clamp(v, lo, hi)
return math.max(lo, math.min(hi, v))
end
-- Self-test: only runs when executed directly
if debug.getinfo(2, "S") == nil then
-- Running as main script, not required
print("Testing clamp...")
assert(M.clamp(5, 0, 10) == 5)
assert(M.clamp(-1, 0, 10) == 0)
assert(M.clamp(15, 0, 10) == 10)
print("All tests passed!")
end
return Mتحقق سريع
ما الطريقة القياسية لتعريف الحالة الخاصة في وحدة Lua؟
مراجعة: كتابة الوحدات
الملخص:
- النمط:
local M = {} ... return M - المتغيرات المحلية في الملف = خاصة؛ وحقول M = واجهة عامة
- يُنفَّذ رمز مستوى الوحدة مرة واحدة عند أول require
- صدّروا الأصناف من خلال دالة إنشاء في جدول الوحدة
- التحميل الكسول للوحدات الفرعية باستخدام
__index - أدرجوا
_VERSIONللتحقق من التوافق
الأسئلة الشائعة
هل درس «كتابة ملف وحدة» مجاني؟
نعم — نص درس «كتابة ملف وحدة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Lua Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Lua Academy 4 دروس في المجموع.
ماذا ستتعلم في «كتابة ملف وحدة»؟
أنشئ وحدة بإرجاع جدول من الدوال من ملف .lua تتمرن على Lua Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Lua Academy؟
لا تُشترط خبرة سابقة. Lua Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «كتابة ملف وحدة»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Lua Academy هذا؟
نعم. كل درس في Lua Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.