Дополнительные действия
Enables equal treatment of Lua and wikicode users for modules. Using this module means you will no longer need to have two different entry points for each function—both Lua and wikicode can call the same function. ==Usage== Using this module is straightforward. Here's an example:
local Class = require('Module:Class') <!--- Add the import local Cool = Class.new() <!--- Create a class function Cool.doCoolStuff(a, b) <!--- Note the colon symbol! return a + b end return Cool.export() <!--- Export the table
Now, doCoolStuff can be called from both Lua and wikicode with the same arguments.
To illustrate, you can use Cool
(2, 3) in Lua, and also use {{#invoke
|doCoolStuff|2|3}} in wikicode, and both will return 5.
===Named Arguments=== When named arguments are provided, there's a slight change. Named arguments are supplied as a Lua table and are always the first argument. Here's how:
local Class = require('Module:Class') <!--- Add the import local Cool = Class.new() <!--- Create a class function Cool.doCoolStuff(args, a, b) <!--- Named args are now the first argument! return a + b + args.c end return Cool.export() <!--- Export the table
You can now call Cool
({c = 5}, 2, 3) in Lua, and similarly use {{#invoke
|doCoolStuff|2|3|c=5}} in wikicode, and both will return 10.
===Advanced Usage=== Module:Class supports advanced usage scenarios via the export function's options parameter. These options are passed directly to the Module:Arguments, allowing you to specify features such as frame inheritance, trimming, and more. For more details, refer to iCCup's Module
documentation.
API
-
Программное имя: Class
Adjusts the provided table so that its public functions (those not prefixed with an underscore) are usable from both Lua and wikicode, and returns the modified table. Note: Avoid creating underscored versions of your public methods—use distinct names. For instance, don't use both copy() and _copy() in the same module. The options parameter allows passing arguments to Module:Arguments's getArgs method.
Creates a new class by setting the proper metadata. If a base class is provided, it will be used as the base. An optional init function can act as a constructor. If only init is provided, it functions independently.
Посмотрите всю нашу документацию iCCup здесь.
local Arguments = require('Module:Arguments')
local Class = {}
Class.PRIVATE_FUNCTION_SPECIFIER = '_'
---@class BaseClass
---@operator call:self
---@field is_a fun(self, BaseClass):boolean
function Class.new(base, init)
local instance = {}
if not init and type(base) == 'function' then
init = base
base = nil
elseif type(base) == 'table' then
for index, value in pairs(base) do
instance[index] = value
end
instance._base = base
end
instance.__index = instance
local metatable = {}
metatable.__call = function(class_tbl, ...)
local object = {}
setmetatable(object, instance)
instance.init(object, ...)
return object
end
instance.init = function(object, ...)
if base then
base.init(object, ...)
end
if init then
init(object, ...)
end
end
instance.export = function(options)
return Class.export(instance, options)
end
instance.is_a = function(self, class)
local m = getmetatable(self)
while m do
if m == class then
return true
end
m = m._base
end
return false
end
setmetatable(instance, metatable)
return instance
end
---@generic T:table
---@param class T
---@param options ?table
---@return T
function Class.export(class, options)
for name, f in pairs(class) do
-- We only want to export functions, and only functions which are public (no underscore)
if (
type(f) == 'function' and
(not string.find(name, Class.PRIVATE_FUNCTION_SPECIFIER))
) then
class[name] = Class._wrapFunction(class[name], options)
end
end
return class
end
local Table = {}
-- Duplicate Table.isNotEmpty() here to avoid circular dependencies with Table
function Table.isNotEmpty(tbl)
-- luacheck: push ignore (Loop can be executed at most once)
for _ in pairs(tbl) do
return true
end
-- luacheck: pop
return false
end
---
-- Wrap the given function with an argument parser so that both wikicode and lua
-- arguments are accepted
--
function Class._wrapFunction(f, options)
options = options or {}
local alwaysRewriteArgs = options.trim
or options.removeBlanks
or options.valueFunc ~= nil
return function(...)
-- We cannot call getArgs with a spread operator when these are just lua
-- args, so we need to wrap it
local input = {...}
local frame = input[1]
local shouldRewriteArgs = alwaysRewriteArgs
or (
#input == 1
and type(frame) == 'table'
and type(frame.args) == 'table'
)
if shouldRewriteArgs then
local namedArgs, indexedArgs = Class._frameToArgs(frame, options)
if namedArgs then
return f(namedArgs, unpack(indexedArgs))
else
return f(unpack(indexedArgs))
end
else
return f(...)
end
end
end
--[[
Translates a frame object into arguments expected by a lua function.
]]
function Class._frameToArgs(frame, options)
local args = Arguments.getArgs(frame, options)
-- getArgs adds a metatable to the table. This breaks unpack. So we remove it.
-- We also add all named params to a special table, since unpack removes them.
local indexedArgs = {}
local namedArgs = {}
for key, value in pairs(args) do
if type(key) == 'number' then
indexedArgs[key] = value
else
namedArgs[key] = value
end
end
return (Table.isNotEmpty(namedArgs) and namedArgs or nil), indexedArgs
end
-- Реализация метода instanceOf
function Class.instanceOf(object, class)
-- Проверяем, является ли объект экземпляром класса
if type(object) == 'table' and object.__index == class then
return true
end
-- Проверяем для наследуемых классов
local super = object._base
while super do
if super == class then
return true
end
super = super._base
end
return false
end
return Class