python - 实例方法应该写在类层次结构中的什么位置?

标签 python oop language-agnostic software-design

这是我用于模拟模型的类“层次结构”的一部分(我的代码是用 Python 编写的,但我认为我的问题与语言无关):

class World:
# highest-level class, which "knows" everything about the model
# most likely will have just one instance
# contains (e.g., in a dictionary) references to all the instances of class Agent

class Agent:
# each instance represents an agent
# an agent can, among other things, move around according to certain rules
# movement depends on the internal state of the agent,
# but also on the terrain and other information not stored in the Agent instance

问题:move实例方法应该放在哪里?

我想我应该将 class Agent 的依赖限制在层次结构中比它本身低的类(即,其实例包含在 Agent 实例中的类) .但这意味着 move 方法不能在 class Agent 中,因为它创建了对描述地形等的类(至少是接口(interface))的依赖 - 所以我不妨添加Agent 引用(因此依赖于)World。从软件设计的角度来看,这可以吗?

另一种方法是将方法 move 放在 class World 中,这样它就不会产生任何额外的依赖关系。然而,class World 将完成几乎所有的工作,在我看来,这将违背 OOP 的主要思想(我的理解是不要将所有功能堆放在一个地方,而是将其包含在相关类中)。

性能方面的考虑只是次要问题(而且我不认为两种方法之间的性能会有差异)。

编辑:我误用了上面的“类层次结构”这个词。我指的不是继承层次结构,而是一堆实例相互包含的类。

最佳答案

您需要考虑的是 Single Responsibility Principle .基本上,每个类都应该负责一件“事情”,并且应该完全封装那一项责任。而且你应该只继承责任延伸的地方。你应该总是能够说扩展类是父类的 100% 甚至更多(在特定意义上更多)。您永远不应该遇到 child 是 parent 的子集并且“更少”的情况。因此,扩展世界的人不是一个好的设计,因为世界的某些方面与人无关。

因此,如果我们看一个示例,您会把实例方法放在由该特定类的角色决定的级别上。那么,让我们更明确地看一个例子:

class Person:
    name: ""
    birthDate: ""

class PoliceOfficer extends Person:
    badgeNumber: ""

显然这是伪代码,但它演示了正在发生的事情。

现在,您要在哪里添加 move() 方法?我们可以将它添加到 PoliceOfficer 中,但是这样我们就会破坏 Person 的封装,因为人也可以移动。

class Person:
    def move(world):

但是,我们要在哪里添加 issueTicket() 方法呢?广义的 Person 不能开票,所以如果我们把它添加到 Person 类中,我们就违反了它的职责。因此,我们将它添加到 PoliceOfficer,因为这是有意义的地方。

就创建依赖性而言,您应该 always favor composition over inheritance .所以从这个意义上说,可以有任意多的依赖关系,因为它们都是软依赖关系(好吧,有点)。由于 move() 采用 world 的实例(或具有世界接口(interface)的对象),因此依赖项被推出类并进入调用代码。这样一来,您的类(class)代码就可以保持相当开放和无依赖性,同时仍能保持高效。

硬编码依赖项通常被视为不好的做法。但是注入(inject)它们(通过依赖注入(inject)或组合)通常被视为一件好事。

总结:将实例方法放在逻辑上有意义的地方。

关于python - 实例方法应该写在类层次结构中的什么位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4860686/

相关文章:

python - 保存带有时间戳的视频帧

python - 不同的 :maxdepth: for specific entries in toctree (Sphinx)

c++ - 在 OOP 中使用类 C API

php - PHP MVC 框架中面向目标的设计

optimization - 长变量名是否浪费内存?

language-agnostic - 关于 API 我不明白什么?

python - Manage.py已添加到PYTHONPATH,但找不到

python - PySerial Readline 进入无限循环

javascript - 为什么 Javascript 不能正确绑定(bind)我的点表达式?

database - 有谁知道一个很好的图书馆可以将一个人的名字映射到他或她的性别?