如何高效地链接多个类
背景: 我正在用Python开发一个游戏,为了保持代码的整洁和有序,我创建了一个文件夹,里面有多个Python文件,每个文件里都有一个大类,比如“MapEngine”(地图引擎)或“NPCEngine”(NPC引擎)。
在main.py文件中,我从每个文件加载这些类,并通过一个“Game”类把它们连接在一起,像这样:
from folder import *
class Game:
def __init__(self):
self.MapEngine = MapEngine.MapEngine()
...
def loop(self):
...
由于像“CollisionEngine”(碰撞引擎)这样的类需要从其他类(比如“MapEngine”)获取数据,我通常会在前者(即CollisionEngine)中给后者(即MapEngine)分配一些变量,以便使用MapEngine加载的地图数据或功能:
class CollisionEngine:
def __init__(self, MapClass, ...):
self.MapEngine = MapClass
问题: 但是,由于许多类需要相互连接,过了一段时间后,我发现很难搞清楚应该先加载哪个类来分配变量。此外,像“EventEngine”(事件引擎)这样的类需要访问其他所有类。我的代码变得难以阅读,当两个类彼此同样重要时,我也很困惑。
疑问: 我听说过类的继承,但我觉得在这里不适用,因为每个类的功能都很不同。那么,有没有办法优雅地将每个类连接在一起,就像它们都是一个大类的一部分?换句话说,有没有办法在一个类内部引用其他类的变量?
(我的想法:也许我可以写一个叫“Request”的类,它可以作为一个顶层的类管理器。不过,我觉得我可能需要使用像exec()或eval()这样的函数,这些函数效率不高,而且有点危险。)
这是我的第一次发帖,我尽量表达得清楚明了,如果有不明白的地方请问我,谢谢你的回复!
2 个回答
考虑把你的项目分成几个层次,这样可以帮助你更好地组织代码,让导入的内容看起来更自然。
这个原则是,代码的下层“蛋糕”不应该依赖于(也就是不应该导入)上层的代码。
举个例子,你可以有一个基础层,这里包含一些常用的数据结构、工具类和算法,这些在你项目的不同层次中都会用到。
接着,你可以有一个模型层,这一层依赖于基础层(也就是使用基础层中的数据结构、工具和算法),但不依赖于其他层。模型层提供了领域内对象的模型。
然后,你可能会有一个游戏层,这一层依赖于模型层(所以在游戏层中的模块可以从模型层导入内容,但反过来就不行)。
经过多次尝试,我找到了一种(虽然不太完美)解决我问题的方法。当然,正如eddiewould所建议的,我会对我的代码进行更好的组织,并增加多个层级。不过,如果你想让多个类相互关联,只需在主类中添加一个变量(这个主类会调用所有其他类)到每个类中。我觉得用代码示例来说明会更清楚:
main.py
engine_folder
----> engine_1.py
----> engine_2.py
在main.py中,engine_1和engine_2被加载:
from engine_folder import engine_1, engine_2
class game:
def __init__(self):
self.engine_1 = engine_1.engine(self, ...)
self.engine_2 = engine_2.engine(self, ...)
#where engine_1.engine and engine_2.engine are
#two classes that need to transfer data between
#each other
def run(self):
self.engine_1.run()
self.engine_2.run()
注意engine_1.engine的第一个参数是self,这个self指的是调用这个类的顶层类。现在,在engine_1中,如果我们想打印engine_2中的一个变量,类的写法大概是这样的:
class engine:
def __init__(self, top_level_class, ...):
self.top_level_class = top_level_class
def run(self):
print self.top_level_class.engine_2.random_var
这样写是很不错的(虽然print self.top_level_class.engine_2.random_var这个写法有点长),但相比于下面这样的写法:
class EventEngine:
def __init__(self, Camera_Class, Map_Class, Character_Class, Skill_Class,
Interface_Class, Sprite_Class, Dialog_Class, Game_Class,
Item_Class):
self.ItemEngine = Item_Class
self.GameEngine = Game_Class
self.DialogEngine = Dialog_Class
self.SpriteEngine = Sprite_Class
self.SkillEngine = Skill_Class
self.CameraEngine = Camera_Class
self.MapEngine = Map_Class
self.CharacterEngine = Character_Class
self.IEngine = Interface_Class
新的版本:
class EventEngine:
def __init__(self, top_level_class):
self.top = top_level_class
#a var from Map_Class can be called as such:
#self.top.MapEngine.map[0][1]
#and I can call variables from every class, not only those I
#have loaded like before
要好得多,代码也更简洁。