在类层次结构中应在何处编写实例方法? [英] where in class hierarchy should instance methods be written?

查看:78
本文介绍了在类层次结构中应在何处编写实例方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我用于仿真模型的类层次结构"的一部分(我的代码在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.

推荐答案

您需要考虑的是.基本上,每个类都应该对一个事物"负责,并且应该完全封装这一责任.而且,您应该仅继承责任扩展的地方.您应该总是可以说扩展类是父类的100%或更多(在特定意义上更多).您永远不要让孩子成为父母的子集并且少"一个孩子.因此,扩展世界的人并不是一个好的设计,因为世界的某些方面与一个人无关.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆