First, I'd take a hard look at why Entity:getPlayer
needs to exist and why it
creates a new player. (Even if that's sample code, why does entity depend on
player and not only the other way around?)
Let's look at several ways to solve this problem without global variables.
TL;DR: Follow the "Module split" solution.
Runtime require
This is @Egor's solution. It moves the module import from file loading time to runtime. This hides your dependencies a bit, but it's a minimal change to solve a require loop.
classes/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
Data Injection
Pass the player into the entities that need it.
classes/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
classes/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
Logic injection
I don't like this solution because it requires that you always require
entity.lua with the same path. Lua modules may have different definitions if
sometimes you use require('classes/Entity')
and other times
require('classes.Entity')
. This might be a good pattern for partial classes,
but that doesn't look like what you're doing. Regardless, listed for
completeness.
If you had a global for Entity or another module that owned it, you could do
the injection there to solve the path risk.
classes/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
Module split
This is one of the cleanest solutions. When you have two things that depend on
each other, make them independent and move the dependency into a higher module.
However, it's also the furthest away from your current code. It's likely that
you end up using an instance of Population like a global variable, but there's
no requirement for it to be global.
classes/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