Lua - 太多 C 级别(限制为 200)

eli*_*00d 6 lua dependencies require

我最近遇到了一个问题,我看到错误“太多 C 级别(限制为 200)”。

它到底意味着什么?我该如何防止这种情况发生?

我认为这与循环需求有关,但它指向我的代码中创建类的新实例的一行,如下所示:

Class:new()
Run Code Online (Sandbox Code Playgroud)

至于我的模块,我确实有一些循环需求,但我尝试通过将外部类移动到同一个模块中来修复它们,如下所示:

Class.SubClass = Class:new()
Run Code Online (Sandbox Code Playgroud)

有什么想法吗?

更新:

这是我遇到的一个例子:

lua类

local Class = {}

function Class:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    return o
end

return Class
Run Code Online (Sandbox Code Playgroud)

类/Entity.lua

local Class = require('Class')
local Player = require('classes/Player')

local Entity = Class:new()

function Entity:getPlayer() 
    return Player:new() 
end

return Entity
Run Code Online (Sandbox Code Playgroud)

类/Player.lua

local Class = require('Class')
local Entity = require('classes/Entity')

local Player = Class:new()

function Player:getEntities() 
    local entities = {}
    for i = 1, 100 do
        entities[i] = Entity:new()
    end
    return entities
end

return Player
Run Code Online (Sandbox Code Playgroud)

我意识到这是一个循环依赖,但我找到的唯一解决方案是:Lua:如何避免循环需要,它使用全局变量。当地人有办法避免这种情况吗?

idb*_*rii 2

首先,我会仔细研究为什么Entity:getPlayer需要存在以及为什么它会创造一个新的玩家。(即使这是示例代码,为什么实体依赖于玩家而不是相反?)

让我们看一下在没有全局变量的情况下解决这个问题的几种方法。

TL;DR:遵循“模块拆分”解决方案。

运行时要求

这是@Egor 的解决方案。它将模块导入从文件加载时间移至运行时。这稍微隐藏了您的依赖项,但这是解决 require 循环的最小更改。

类/Entity.lua

local Class = require('Class')
local Player

local Entity = Class:new()

function Entity:getPlayer() 
    Player = Player or require('classes/Player')
    return Player:new() 
end

return Entity
Run Code Online (Sandbox Code Playgroud)

数据注入

将玩家传递给需要它的实体。

类/Entity.lua

local Class = require('Class')
local Player = require('classes/Player')

local Entity = Class:new()

function Entity:init(player_class) 
    self.player_class = player_class
end

function Entity:getPlayer() 
    return self.player_class:new()
end

return Entity
Run Code Online (Sandbox Code Playgroud)

类/Player.lua

local Class = require('Class')
local Entity = require('classes/Entity')

local Player = Class:new()

function Player:getEntities() 
    local entities = {}
    for i = 1, 100 do
        -- Or instead, we might pass the relevant player instance (self).
        entities[i] = Entity:new(Player)
    end
    return entities
end

return Player
Run Code Online (Sandbox Code Playgroud)

逻辑注入

我不喜欢这个解决方案,因为它要求您始终需要具有相同路径的entity.lua。如果有时使用require('classes/Entity'),有时 使用,Lua 模块可能有不同的定义require('classes.Entity')。对于部分类来说,这可能是一个很好的模式,但这看起来不像你正在做的事情。无论如何,列出是为了完整性。

如果您有一个全局实体或拥有它的另一个模块,您可以在那里进行注入以解决路径风险。

类/Player.lua

local Class = require('Class')
local Entity = require('classes/Entity')

local Player = Class:new()

...

-- Adding functionality to an imported module.
function Entity:getPlayer() 
    return Player:new() 
end


return Player
Run Code Online (Sandbox Code Playgroud)

模块拆分

这是最干净的解决方案之一。当您有两个相互依赖的东西时,使它们独立并将依赖关系移到更高的模块中。然而,它也是距离当前代码最远的。您最终可能会像全局变量一样使用 Population 实例,但并不要求它是全局变量。

类/Population.lua

local Class = require('Class')
local Entity = require('classes/Entity')
local Player = require('classes/Player')

local Population = Class:new()

function Population:getPlayer() 
    return Player:new() 
end

function Population:getEntities() 
    local entities = {}
    for i = 1, 100 do
        entities[i] = Entity:new()
    end
    return entities
end

return Population
Run Code Online (Sandbox Code Playgroud)