You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.6 KiB
105 lines
3.6 KiB
|
5 years ago
|
-------------------------------------------------------------------------------
|
||
|
|
---------------------------------- NAMESPACE ----------------------------------
|
||
|
|
-------------------------------------------------------------------------------
|
||
|
|
|
||
|
|
local _, ns = ...
|
||
|
|
|
||
|
|
-------------------------------------------------------------------------------
|
||
|
|
------------------------------------ CLASS ------------------------------------
|
||
|
|
-------------------------------------------------------------------------------
|
||
|
|
|
||
|
|
ns.Class = function (name, parent, attrs)
|
||
|
|
if type(name) ~= 'string' then error('name param must be a string') end
|
||
|
|
if parent and not ns.IsClass(parent) then error('parent param must be a class') end
|
||
|
|
|
||
|
|
local Class = attrs or {}
|
||
|
|
Class.getters = Class.getters or {}
|
||
|
|
Class.setters = Class.setters or {}
|
||
|
|
|
||
|
|
local instance_metatable = {
|
||
|
|
__tostring = function (self)
|
||
|
|
return '<'..name..' instance at '..self.__address..'>'
|
||
|
|
end,
|
||
|
|
|
||
|
|
__index = function (self, index)
|
||
|
|
-- Walk up the class hierarchy and check for a static value
|
||
|
|
-- followed by a getter function on each parent class
|
||
|
|
local _Class = Class
|
||
|
|
repeat
|
||
|
|
-- Use rawget to skip __index on Class, we want to
|
||
|
|
-- check each class object individually
|
||
|
|
local value = rawget(_Class, index)
|
||
|
|
if value ~= nil then return value end
|
||
|
|
local getter = _Class.getters[index]
|
||
|
|
if getter then return getter(self) end
|
||
|
|
_Class = _Class.__parent
|
||
|
|
until _Class == nil
|
||
|
|
end,
|
||
|
|
|
||
|
|
__newindex = function (self, index, value)
|
||
|
|
local setter = Class.setters[index]
|
||
|
|
if setter then
|
||
|
|
setter(self, value)
|
||
|
|
else
|
||
|
|
rawset(self, index, value)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
}
|
||
|
|
|
||
|
|
setmetatable(Class, {
|
||
|
|
__call = function (self, ...)
|
||
|
|
local instance = {}
|
||
|
|
instance.__class = Class
|
||
|
|
instance.__address = tostring(instance):gsub("table: ", "", 1)
|
||
|
|
setmetatable(instance, instance_metatable)
|
||
|
|
instance:Initialize(...)
|
||
|
|
return instance
|
||
|
|
end,
|
||
|
|
|
||
|
|
__tostring = function ()
|
||
|
|
return '<class "'..name..'">'
|
||
|
|
end,
|
||
|
|
|
||
|
|
-- Make parent class attributes accessible on child class objects
|
||
|
|
__index = parent
|
||
|
|
})
|
||
|
|
|
||
|
|
if parent then
|
||
|
|
-- Set parent class and allow parent class setters to be used
|
||
|
|
Class.__parent = parent
|
||
|
|
setmetatable(Class.setters, { __index = parent.setters })
|
||
|
|
elseif not Class.Initialize then
|
||
|
|
-- Add default Initialize() method for base class
|
||
|
|
Class.Initialize = function (self) end
|
||
|
|
end
|
||
|
|
|
||
|
|
return Class
|
||
|
|
end
|
||
|
|
|
||
|
|
-------------------------------------------------------------------------------
|
||
|
|
----------------------------------- HELPERS -----------------------------------
|
||
|
|
-------------------------------------------------------------------------------
|
||
|
|
|
||
|
|
ns.IsClass = function (class)
|
||
|
|
return type(class) == 'table' and class.getters and class.setters
|
||
|
|
end
|
||
|
|
|
||
|
|
ns.IsInstance = function (instance, class)
|
||
|
|
if type(instance) ~= 'table' then return false end
|
||
|
|
local function compare (c1, c2)
|
||
|
|
if c2 == nil then return false end
|
||
|
|
if c1 == c2 then return true end
|
||
|
|
return compare(c1, c2.__parent)
|
||
|
|
end
|
||
|
|
return compare(class, instance.__class)
|
||
|
|
end
|
||
|
|
|
||
|
|
ns.Clone = function (instance, newattrs)
|
||
|
|
local clone = {}
|
||
|
|
for k, v in pairs(instance) do clone[k] = v end
|
||
|
|
if newattrs then
|
||
|
|
for k, v in pairs(newattrs) do clone[k] = v end
|
||
|
|
end
|
||
|
|
return instance.__class(clone)
|
||
|
|
end
|