Вот такой класс получился нормально?
https://github.com/Clor0xD/OpenComputers2IDE.git посмотреть lua ооп потуги можно тут)
https://github.com/Tencent/LuaHelper отличный плагин на vscode классы (включая множественное наследование), типы, подсказки, аннотации
---@class IRunable
local IRunable
IRunable = {class = "Interface IRunable"}
function IRunable:run(...)
self:noImplIntefaceError("run(...)", IRunable:getClassName())
end
return IRunable
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by User.
--- DateTime: 20.04.2022 20:14
---
local Class = require('libEx/Class')
local sides = require("sides")
---@class Position:Class
---@field public x number
---@field public y number
---@field public z number
---@field public r PositionSide
local Position = Class:extended({
class = "Class Position"
})
---@class PositionSide
Position.side = {
north = 0,
east = 1,
south = 2,
west = 3,
negZ = 0,
posX = 1,
posZ = 2,
negX = 3
}
---@class PositionSidesBySide
Position.sidesBySide = {
[Position.side.negZ] = sides.negz,
[Position.side.posX] = sides.posx,
[Position.side.posZ] = sides.posz,
[Position.side.negX] = sides.negx
}
---@class PositionSideBySides
Position.sideBySides = {
[sides.negy] = Position.side.negZ,
[sides.posy] = Position.side.negZ,
[sides.negz] = Position.side.negZ,
[sides.posx] = Position.side.posX,
[sides.posz] = Position.side.posZ,
[sides.negx] = Position.side.negX
}
---@class PositionTurn
Position.turn = {
left = -1,
forward = 0,
right = 1,
around = 2,
back = 2
-- left = 3
}
---@param x number
---@param y number
---@param z number
---@param r PositionSide
---@return Position
function Position:new(x, y, z, r)
local instance = self.super:new()
if not x then
return self:extendedInstance(instance):set(0, 0, 0, 0)
end
return self:extendedInstance(instance):set(x, y, z, r)
end
---@param adjacentPosition Position
---@return boolean,Sides @staus globalRotation:Sides_openOs
function Position:getAdjacentSide(adjacentPosition)
local this, adjacent, acc, check, result = self:get("yzx", true), adjacentPosition:get("yzx", true), 0, 0, 0
for i = 1, 3 do
check = adjacent[i] - this[i]
if check == 1 then
result = i * 2 - 1
elseif check == -1 then
result = i * 2 - 2
end
acc = acc + check
end
return acc == 1 or acc == -1, result
end
---@ changes self
---@param positionORx Position
---@param y number
---@param z number
---@return Position @self
function Position:add(positionORx, y, z)
if positionORx.class then
self.x = self.x + positionORx.x
self.y = self.y + positionORx.y
self.z = self.z + positionORx.z
return self
end
self.x = self.x + positionORx
self.y = self.y + y
self.z = self.z + z
return self
end
---@ changes self
---@param position Position
---@return Position @self
function Position:sub(position)
self.x = self.x - position.x
self.y = self.y - position.y
self.z = self.z - position.z
return self
end
---@ does not change sefl, args
---@param position Position
---@return number, number, number @x,y,zlua
function Position:subCortage(position)
return self.x - position.x, self.y - position.y, self.z - position.z
end
function Position:coordsEquels(position)
return self.x == position.x and self.y == position.y and self.z == position.z
end
function Position:equels(position)
return self == position or
(self.x == position.x and self.y == position.y and self.z == position.z and self.r == position.r)
end
function Position:get(format, isPack)
if format == nil then
if isPack then
return {self.x, self.y, self.z, self.r}
end
return self.x, self.y, self.z, self.r
end
if self:assertFormat(format) then
local result = {}
for key in format:gmatch '[xyzr]' do
table.insert(result, self[key])
end
if isPack then
return result
end
return table.unpack(result)
end
end
function Position:setf(format, ...)
self:assertFormat(format)
local args = table.pack(...)
assert(#format <= #args, self:tostring() .. ":setf(format, ...) argument (...) very short")
for i = 1, #format do
self[format:sub(i, i)] = args[i]
end
return self
end
function Position:set(x, y, z, r)
-- self.x, self.y, self.z, self.r = x, y, z, r
-- return self
return self:setf("xyzr", x, y, z, r) -- assert params
end
function Position:clone() -- local returnPos; returnPos = currentPos:clone()
return self:new(self:get())
end
function Position:copy(position) -- returnPos:copy(currentPos)
return self:set(position:get())
end
function Position:getCoordinatesUp()
local x, y, z, r = self:get()
return x, y + 1, z, r
end
function Position:getCoordinatesDown()
local x, y, z, r = self:get()
return x, y - 1, z, r
end
function Position:getCoordinatesLocalRotation(turn)
self:getCoordinatesGlobalRotation((turn + self.r) % 4)
end
function Position:getCoordinatesGlobalRotation(side)
local x, y, z, r = self:get()
if side == self.side.negZ then
z = z - 1
elseif side == self.side.posZ then
z = z + 1
elseif side == self.side.negX then
x = x - 1
elseif side == self.side.posX then
x = x + 1
end
return x, y, z, r
end
function Position:turnRight()
self.r = (self.r + 1) % 4
return self
end
function Position:turnLeft()
self.r = (self.r - 1) % 4
return self
end
function Position:turnAround()
self.r = (self.r + 2) % 4
return self
end
function Position:stepUp()
self.y = self.y + 1
return self
end
function Position:stepDown()
self.y = self.y - 1
return self
end
function Position:stepForward()
return self:stepBase(1)
end
function Position:stepBack()
return self:stepBase(-1)
end
function Position:calculateTurn(globalRotation)
return ((globalRotation - self.r) + 4) % 4
end
---@private
function Position:assertFormat(format, message)
if not format or type(format) ~= 'string' then
format = type(format)
-- if not massage then
message = ' incorrect argument format type : ' .. format .. ' [xyzr] string only'
-- end
error(self:tostring() .. message)
end
if #format == 0 then
-- if not massage then
message = 'incorrect argument format : empty_string'
-- end
error(self:tostring() .. message)
end
if not massage then
message = ' incorrect argument format : ' .. format .. ' [xyzr] only'
end
return assert(not format:match '[^xyzr]', self:tostring() .. message)
end
---@private
function Position:stepBase(dir)
if self.r == self.side.negZ then
self.z = self.z - dir
elseif self.r == self.side.posZ then
self.z = self.z + dir
elseif self.r == self.side.negX then
self.x = self.x - dir
elseif self.r == self.side.posX then
self.x = self.x + dir
end
return self
end
function Position:toStringDebug()
return "x: " .. tostring(self.x) .. " y:" .. tostring(self.y) .. " z:" .. tostring(self.z) .. " r:" ..
tostring(self.r)
end
function Position:print()
print(self:toStringDebug())
return self
end
return Position
--
-- Created by Clor#D on 17.05.2020.
-- ©SofaSolt, 2020
--
---@class Class
---@field public class string
---@field public super Class
---@field public isInstance boolean
---@field public clazz Class @ is not instanse class
local Class
if Class then
return Class
end
Class = {}
Class.class = "Class Class"
Class.isInstance = false
Class.super = Class
Class.clazz = Class
function Class:tostring()
return tostring(self) .. " " .. self.class
end
function Class:extended (child) -- child = {}
-- наследование статичестой части таблица Class, child.super доступ к статической таблице родителя
child.super = self
setmetatable(child, { __index = self, isInstance = false})
child.clazz = child
return child
end
---@class Interface
---@field public class string
---@param ... Interface
function Class:implements(...)
---@type Interface[]
local interfaceList = table.pack(...)
for _,interface in ipairs(interfaceList) do
interface.super = self.super
setmetatable(interface, { __index = self.super, isInstance = false})
self.super = interface
setmetatable(self, { __index = interface, isInstance = false})
end
return self
end
function Class:extendedInstance(instance)
-- наследование экземпляра таблица instance
setmetatable(instance, self)
self.__index = self
return instance
end
function Class:new()
local instance = {isInstance = true}
return self.clazz:extendedInstance(instance)
end
function Class:noImplError(funcName)
if not funcName then
funcName = 'unknownFunc'
end
error(self:tostring() .. ':' .. funcName .. ' no implementation')
end
function Class:noImplIntefaceError(funcName, interfaceName)
if not funcName then
funcName = 'unknownIntefaceFunc'
end
error(self:tostring() .. ':' .. funcName .. ' no implementation '..interfaceName..":"..funcName)
end
function Class:assert(param, message)
if not message then
message = 'assert unknown param'
end
return assert(param, self:tostring() .. message)
end
function Class:assertNumberSetDefault(number, default, message)-- number = '100'
if not message then
message = 'assert unknown param'
end
if number == nil then
if tonumber(default) then
number = default
else
error(self:tostring() .. message .. " is nil")
end
end
return assert(tonumber(number), self:tostring() .. message .. " not number")
end
function Class:assertNumber(number, message)
return self:assertNumberSetDefault(number, nil, message)
end
function Class:assertEnum(param, enum, message)
for _,element in pairs(enum) do
if param == element then
return param
end
end
self:error(message.." param: "..tostring(param).." not listed")
end
function Class:error(message)
error(self:tostring()..message)
end
function Class.nop()
end
function Class:getClassName()
local _, name = string.gmatch(self.class, "([%a%d].+)%s(.+)")()
return name
end
function Class:getClassLevel()
local type = string.gmatch(self.class, "([%a%d].+)%s(.+)")()
return type
end
function Class:assertInstance(message)
if self.isInstance then
return true
end
self:error(message)
end
function Class:assertSuperParentClass(param, sampleClass, message)
---@type Class
local temp = param
while temp.class ~= Class.class do
if temp.class == sampleClass then
return param
end
temp = temp.super
end
self:error(message.." "..param.class.." not extended "..sampleClass)
end
---@param fieldName string
---@param fileldValue any
function Class:createFieldIfMissing(fieldName, fileldValue)
if self[fieldName] == nil then
self[fieldName] = fileldValue
end
end
return Class
--[[ Using
Class = require("/oop/Class")
local Implementation
if Implementation then
return Implementation
end
Implementation = Class:extended({})-- "наследования" класса, по сути соеденение статических таблиц в иерархию наследования
Implementation.class = "Implementation"
function Implementation:toString()
return self.class
end
function Implementation:new(stringParent, stringChildren)
local instance = self.super:new(stringParent) -- конструктор предка
self.stringC = stringChildren
return self:extendedInstance(instance) -- "наследования" экземпляра, по сути соеденение таблиц экземляра в иерархию наследования
end
return Implementation
]]