کلاس‌ها و اشیاء در لوا

ساخت کلاس با جدول و متا‌جدول، سازنده (new)، متدها و self

شی‌گرایی در لوا

لوا کلمه کلیدی class ندارد — اما با جدول‌ها و متا‌جدول‌ها می‌توان شی‌گرایی کامل پیاده کرد! این الگو در جامعه لوا استاندارد است.

ساخت یک کلاس

-- تعریف کلاس
local Dog = {}
Dog.__index = Dog     -- مهم! جستجوی متدها

-- سازنده (constructor)
function Dog.new(name, breed)
local self = setmetatable({}, Dog)
self.name = name
self.breed = breed
return self
end

-- متد
function Dog:bark()
return self.name .. " هاپ هاپ!"
end

function Dog:introduce()
return "من " .. self.name .. " هستم، نژاد " .. self.breed
end

-- استفاده
local rex = Dog.new("رکس", "ژرمن")
print(rex:bark())        -- رکس هاپ هاپ!
print(rex:introduce())   -- من رکس هستم، نژاد ژرمن

دو نکته کلیدی

  1. Dog.__index = Dog — وقتی کلیدی در شیء نباشد، در خود کلاس جستجو می‌شود (متدها اینجا هستند)
  2. function Dog:bark() — دونقطه یعنی پارامتر مخفی self اضافه می‌شود

دونقطه در برابر نقطه

-- این دو کاملاً معادلند:
function Dog:bark()
return self.name .. " هاپ!"
end

function Dog.bark(self)
return self.name .. " هاپ!"
end

-- و در فراخوانی:
rex:bark()        -- معادل:
rex.bark(rex)     -- self خودکار پاس می‌شود
اشتباه رایج: فراخوانی با نقطه و فراموشی self — rex.bark() خطا می‌دهد چون self پاس نشده!

مثال کامل: کلاس حساب بانکی

local Account = {}
Account.__index = Account

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

function Account:deposit(amount)
self.balance = self.balance + amount
return self.balance
end

function Account:withdraw(amount)
if amount > self.balance then
return nil, "موجودی کافی نیست!"
end
self.balance = self.balance - amount
return self.balance
end

function Account:getInfo()
return string.format("%s: %.0f تومان", self.owner, self.balance)
end

-- استفاده
local acc = Account.new("علی", 100000)
acc:deposit(50000)
print(acc:getInfo())   -- علی: 150000 تومان

local ok, err = acc:withdraw(999999)
if not ok then print(err) end   -- موجودی کافی نیست!

هر شیء مستقل است

local a1 = Account.new("علی", 100)
local a2 = Account.new("مریم", 200)

a1:deposit(50)
print(a1.balance)   -- 150
print(a2.balance)   -- 200 (دست‌نخورده!)

__tostring برای کلاس

function Account:__tostring()
return "حساب[" .. self.owner .. "]: " .. self.balance
end

-- حالا print مستقیم کار می‌کند
print(a1)   -- حساب[علی]: 150
الگوی کلاس لوا را حفظ کنید: جدول + __index + new + متدهای دونقطه. این الگو در همه پروژه‌های لوا (از Roblox تا Neovim) یکسان است!

این مبحث بخشی از دوره آموزش کامل لوا است.

ابزارهای مرتبط