mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-16 22:46:03 +01:00
feat(class): basic class implementation
wip, feedback appreciated.
This commit is contained in:
105
imports/class/shared.lua
Normal file
105
imports/class/shared.lua
Normal file
@@ -0,0 +1,105 @@
|
||||
lib.print.warn('ox_lib\'s class module is experimental and may break without warning.')
|
||||
|
||||
lib.class = {}
|
||||
|
||||
-- Fields added to the "private" field on a class will not be msgpacked.
|
||||
-- Use setters/getters when working with these values.
|
||||
local private_mt = {
|
||||
__ext = 0,
|
||||
__pack = function() return '' end,
|
||||
}
|
||||
|
||||
local function newClass(self, obj)
|
||||
if obj.private then
|
||||
setmetatable(obj.private, private_mt)
|
||||
end
|
||||
|
||||
setmetatable(obj, self)
|
||||
|
||||
if self.init then obj:init() end
|
||||
|
||||
return obj
|
||||
end
|
||||
|
||||
---@param self table
|
||||
---@param metamethod string
|
||||
---@param value any
|
||||
local function setMetamethod(self, metamethod, value)
|
||||
local mt = getmetatable(self)
|
||||
|
||||
if not mt then return error('no metatable') end
|
||||
if not metamethod:match('^__%w+$') then return error('invalid metamethod') end
|
||||
|
||||
rawset(getmetatable(self), metamethod, value)
|
||||
end
|
||||
|
||||
---@param name? string
|
||||
function lib.class.new(name)
|
||||
local data = {}
|
||||
local class = {
|
||||
__index = data,
|
||||
__newindex = data,
|
||||
__name = name or nil,
|
||||
new = newClass,
|
||||
setMetamethod = setMetamethod,
|
||||
}
|
||||
|
||||
return setmetatable(class, class)
|
||||
end
|
||||
|
||||
return lib.class
|
||||
|
||||
--[[
|
||||
---@type table<string, Fruit>
|
||||
local fruits = {}
|
||||
|
||||
---@class Fruit
|
||||
---@field private new fun(self: self, obj): self
|
||||
---@field private setMetamethod fun(self: self, metamethod: string, value: any)
|
||||
---@field private init fun(self: self)
|
||||
---@field private private table
|
||||
---@field name string
|
||||
---@field colour string
|
||||
local Fruit = lib.class.new('Fruit')
|
||||
|
||||
function Fruit:init()
|
||||
print(('Created an %s %s'):format(self:getColour(), self:getName()))
|
||||
fruits[self.name] = self
|
||||
end
|
||||
|
||||
function Fruit:remove()
|
||||
print('Removed', self:getName(), self)
|
||||
fruits[self.name] = nil
|
||||
end
|
||||
|
||||
Fruit:setMetamethod('__gc', function(self) print('ran __gc', self.name) end)
|
||||
|
||||
function Fruit:getName() return self.name end
|
||||
function Fruit:getColour() return self.colour end
|
||||
function Fruit:getSeeds() return self.private.seeds end
|
||||
|
||||
CreateThread(function()
|
||||
local apple = Fruit:new({
|
||||
name = 'apple',
|
||||
colour = 'red'
|
||||
})
|
||||
|
||||
local orange = Fruit:new({
|
||||
name = 'orange',
|
||||
colour = 'orange',
|
||||
private = {
|
||||
seeds = 7
|
||||
}
|
||||
})
|
||||
|
||||
if apple:getColour() == 'red' then
|
||||
print('the apple is red')
|
||||
end
|
||||
|
||||
print(('the orange contains %d seeds'):format(orange:getSeeds()))
|
||||
|
||||
for _, fruit in pairs(fruits) do
|
||||
fruit:remove()
|
||||
end
|
||||
end)
|
||||
]]
|
||||
Reference in New Issue
Block a user