在类层次结构中应在何处编写实例方法? [英] where in class hierarchy should instance methods be written?
问题描述
这是我用于仿真模型的类层次结构"的一部分(我的代码在Python中,但是我认为我的问题与语言无关):
Here's a part of a class "hierarchy" that I use for a simulation model (my code is in Python, but I think my question isn't language dependent):
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
实例方法放在哪里?
Question: where should I put the move
instance method?
我认为应该将class Agent
的依赖关系限制为层次结构中比其本身低的类(即,其实例包含在Agent
实例中的类).但这意味着move
方法不能在class Agent
中,因为它对描述地形等的类(至少是它们的接口)创建了依赖关系-因此我也可能在Agent
中添加对(因此依赖)World
.从软件设计的角度来看可以吗?
I thought I'm supposed to limit the dependency of class Agent
to classes lower in the hierarchy than itself (i.e., classes whose instances are contained in Agent
instances). But that means move
method cannot be in class Agent
since it creates a dependency on (at least the interface of) classes that describe terrain, etc - so I might as well add to Agent
a reference to (and hence a dependency on) World
. Is this ok from software design perspective?
另一种方法是将方法move
放在class World
中,这样不会引起任何其他依赖关系.但是,class World
然后将完成几乎所有的工作,在我看来,这与OOP的主要思想背道而驰(我理解这不是将所有功能都放在一个地方,而是将其包含在其中).相关课程).
The alternative is to put method move
in class World
, where it won't cause any additional dependencies. However, class World
would then be doing almost all the work, and it seems to me that it would go against the main idea of OOP (which I understand as not to pile all the functionality into one place, but rather contain it in the relevant classes).
对性能的考虑仅是次要的考虑(我认为两种方法的性能都不会有所不同).
Performance considerations are only of minor concern (and I don't think performance would differ between the two approaches anyway).
我误用了上面的类层次结构"一词.我指的不是继承层次结构,而是一堆实例彼此包含的类.
I misused the words "class hierarchy" above. I wasn't referring to inheritance hierarchy, just to a bunch of classes whose instances contain each other.
推荐答案
The thing that you need to take into account is the Single Responsibility Principle. Basically, each class should be responsible for one "thing", and should completely encapsulate that one responsibility. And you should only inherit where the responsibility is extended. You should always be able to say that the extending class is 100% of the parent and more (more in a specific sense). You should never have a situation where the child is a subset of the parent and is "less". So a person extending a world is not a good design since there are aspects of the world that do not relate to a person.
因此,如果我们看一个示例,您会将实例方法放在由该特定类的角色所决定的级别上.因此,让我们来看一个更明确的例子:
So, if we look at an example, you would put the instance methods on the level that is dictated by the role of that particular class. So, let's take a more defined look at an example:
class Person:
name: ""
birthDate: ""
class PoliceOfficer extends Person:
badgeNumber: ""
很明显,这是伪代码,但是它演示了正在发生的事情.
Obviously this is pseudocode, but it demonstrates what's happening.
现在,您将在哪里添加move()
方法?我们可以将其添加到PoliceOfficer
,但是由于人也可以移动,因此我们将破坏Person
的封装.
Now, where would you add a move()
method? We could add it to PoliceOfficer
, but then we would break the encapsulation of Person
since a person can also move.
class Person:
def move(world):
但是,我们将在哪里添加issueTicket()
方法?通用Person
无法发行票证,因此,如果将票证添加到Person
类中,我们将无法承担责任.因此,我们将其添加到PoliceOfficer
,因为这才有意义.
But, where would we add an issueTicket()
method? The generalized Person
cannot issue a ticket, so if we added that to the Person
class, we'd be breaking the responsibility of it. So instead, we'd add it to PoliceOfficer
, since that's where it makes sense.
就创建依赖性而言,您应该始终偏重于组合而不是继承.因此,从某种意义上讲,可以有任意多个依赖项,因为它们都是软依赖项(很好).由于move()
接受world
的实例(或具有world接口的对象),因此将依赖项从类中推送到调用代码中.这样一来,您的班级代码就可以保持相当开放和无依赖的状态,同时仍然保持高效.
As far as creating dependency, you should always favor composition over inheritance. So in that sense, there can be as many dependencies as you'd like since they are all soft-dependencies (well, kind of). Since move()
takes an instance of world
(or an object with the world interface), the dependency is pushed out of the class and into the calling code. So that lets your class's code remain pretty open and dependency-free while still being productive.
通常认为对依赖项进行硬编码是不好的做法.但是,通常将它们注入(通过依赖注入或组合)是一件好事.
It's generally seen as bad practice to hard-code dependencies. But injecting them (through Dependency Injection or Composition) is typically seen as a good thing.
摘要::将实例方法放在合理的放置它们的位置.
In summary: Put instance methods where it makes logical sense to put them.
这篇关于在类层次结构中应在何处编写实例方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!