Представляю Вам свою реализацию классов для lua. Классы создаются статически. На данный момент позволяет использовать области видимости static, public и override (private существует отдельно от наработки). Реализовано наследование. Основной задачей было организовать однородную структуру кода вне зависимости от выполняемой задачи и совместимость с EmmyLua (VsCode Lua от sumneko). Буду рад объективной критике. Исправлены ошибки и все объединено в одну область do-end.
API
((
ClassAPI.new(name, parents)
Создание нового класса. Для созданного класса доступны для редактирования
только поля public, static и override. Для скрытия полей public и override рекомендуется
возвращать из области do-end поле static полученного класса.
name : string - имя нового класса.
parents : vararg - список родителей класса в порядке приоритетности.
return table
Создание нового класса. Для созданного класса доступны для редактирования
только поля public, static и override. Для скрытия полей public и override рекомендуется
возвращать из области do-end поле static полученного класса.
name : string - имя нового класса.
parents : vararg - список родителей класса в порядке приоритетности.
return table
ClassAPI.allocate(class)
Создание инстанса класса.
class : table - класс созданный с помощью функции ClassAPI.new.
return table
Создание инстанса класса.
class : table - класс созданный с помощью функции ClassAPI.new.
return table
ClassAPI.isClass(var)
Проверяет является ли переменная классом.
var : any
return boolean
Проверяет является ли переменная классом.
var : any
return boolean
ClassAPI.isInstance(var)
Проверяет является ли переменная инстансом любого класса.
var : any
return boolean
Проверяет является ли переменная инстансом любого класса.
var : any
return boolean
ClassAPI.getClass(instance)
Возвращает класс инстанса.
instance : table - инстанс класса созданный с помощью ClassAPI.allocate.
return table
Возвращает класс инстанса.
instance : table - инстанс класса созданный с помощью ClassAPI.allocate.
return table
ClassAPI.isChild(class1, class2)
Проверяет является ли класс наследником.
class1 : table - класс созданный с помощью функции ClassAPI.new.
class2 : table - класс созданный с помощью функции ClassAPI.new.
return boolean
Проверяет является ли класс наследником.
class1 : table - класс созданный с помощью функции ClassAPI.new.
class2 : table - класс созданный с помощью функции ClassAPI.new.
return boolean
ClassAPI.getPublic(static)
Позволяет получить поле public того же класса. Необходимо для реализации виртуальных функций.
static : table - поле класса "static"
return table - поле класс "public"
Позволяет получить поле public того же класса. Необходимо для реализации виртуальных функций.
static : table - поле класса "static"
return table - поле класс "public"
ClassAPI.getOverride(static)
Позволяет получить поле override того же класса. Необходимо для реализации статических
виртуальных функций.
static : table - поле класса "static"
return table - поле класс "override"
Позволяет получить поле override того же класса. Необходимо для реализации статических
виртуальных функций.
static : table - поле класса "static"
return table - поле класс "override"
ClassAPI.type = ClassDeclare.type
))
))
Пример класса с использованием наработки:
Action
--=========
-- Include
--=========
local lib_modname = Lib.current().modname
local Class = Lib.current().depencies.Class -- Равноценно local Class = ClassAPI
---@type LoggerClass
local Logger = require(lib_modname..'.Logger')
local Log = Logger.getDefault()
---@type UtilsFunctions
local Functions = require(lib_modname..'.Functions')
local checkType = Functions.checkType
--=======
-- Class
--=======
local Action = Class.new('Action')
---@class Action
local public = Action.public
---@class ActionClass
local static = Action.static
---@type ActionClass
local override = Action.override
local private = {}
--========
-- Static
--========
---@alias Callback fun(vararg:any[]):any
---@param callback Callback
---@param owner any
---@param child_instance Action | nil
---@return Action
function override.new(callback, owner, child_instance)
checkType(callback, 'function', 'callback')
if child_instance then
checkType(child_instance, 'Action', 'child_instance')
end
local instance = child_instance or Class.allocate(Action)
private.newData(instance, callback, owner)
return instance
end
--========
-- Public
--========
function public:run(...)
if private.debug then
local success, result = pcall(private.data[self].callback, ...)
if success then
return result
else
Log:err(result)
end
else
return private.data[self].callback(...)
end
end
---@return any
function public:getOwner()
return private.data[self].owner
end
--=========
-- Private
--=========
private.data = setmetatable({}, {__mode = 'k'})
private.debug = true
---@param self Action
---@param callback Callback
---@param owner any
function private.newData(self, callback, owner)
local priv = {
callback = callback,
owner = owner
}
private.data[self] = priv
end
return static
Функция checkType
---@param var any
---@param need_type any
---@param var_name string
---@param level number | nil
function UtilsFunctions.checkType(var, need_type, var_name, level)
if not debug then
return
end
local real_type = type(var)
if real_type == 'userdata' then
local wc3_type_string = tostring(var)
local pos = wc3_type_string:find(':')
local wc3_type = wc3_type_string:sub(1, pos - 1)
if wc3_type ~= need_type then
Log:err('variable \''..(var_name or '')..'\'('..wc3_type..') is not of type '..tostring(need_type), level or 3)
end
return
end
if not ClassAPI.classType(var, need_type) then
Log:err('variable \''..(var_name or '')..'\' is not of type '..tostring(need_type), level or 3)
end
end
Использование:
local action = Action.new(function(a, b) return a/b end)
action:run(1, 0)
--[[ Будет выведена ошибка деление на нуль с указание номера строки "local action = Action.new(function(a, b) return a/b end)" ]]
Класс Action позволяет безопасно запускать функции при private.debug = true. Использую его для действий триггеров, таймеров и т.д, что позволяет оперативно найти ошибку в коде.
Ред. Nelloy
Ред. Nelloy