简单的面向对象编程问题

4
这个问题在我的脑海中出现了好几次。
通过一个例子来解释我的问题。
假设我有两个类: 1- 网格。 2- 单元格。
现在单元格的位置“应该”存储在网格类中,而不是单元格类本身。假设单元格想要通过网格中的一个方法获取它的位置。
那么它该如何做呢?请记住,单元格是由网格类创建/初始化的。
什么样的良好的面向对象方法可以解决这个问题?
谢谢
13个回答

9

我认为这不是一个好的设计。如果单元格需要知道它的位置,它应该自己保存并提供方法供网格访问。


单元格可能不需要保存位置信息。网格可以按需提供位置信息,调用一些具有位置参数的单元格方法。 - m_pGladiator
@ m_pGladiator 当然 - 可能的解决方案有无限多种。我更喜欢先尝试最简单的一种。 - anon
同意如果单元格需要知道它的位置,那么它应该将其存储。但我认为这并不是真正的问题。真正的问题是单元格根本不应该需要知道它的位置。 - John Dibling
@John 我同意,但那就是问题所在。似乎 Cell 是一个可以被丢掉的匿名对象。例如,如果我正在建模一个棋盘,我不确定是否会有一个 Square 类,尽管显然我会有一个 Piece 类或多个类。 - anon
@Neil - Piece 模型确实比 Cell 更好 :) - m_pGladiator

4

我会这样看待它:

  • "Grid"只是由"Cell"集合组成
  • 每个"Cell"都有其在"Grid"中的位置作为数据成员
  • 每个"Cell"可能包含一个"Data"对象,该对象保存"Cell"的实际用户内容

这样,您可以将"Cell"视为网格中的坐标。


这正是我所想的。 - m4design

2
为什么单元格需要知道它在网格中的位置?看起来单元格应该不知道自己的位置。 如果您仍然需要这个 - 单元格可以持有指向其包含网格的指针,并且可以通过请求其位置来询问它(例如,在单元格类内部:getGrid()。getLocation(this))。

2
网格如何知道单元格的位置?搜索?那是个坏主意,会导致太多的引用被传递,这在C++中并不是一个好主意。 - user90843
通常网格是单元格的父元素,因此它知道它们的位置。 - m_pGladiator
你可以反过来问:为什么网格需要知道其单元格的位置?“所有这些单元格组成了网格”可能已经足够了。 - Joris Timmermans
-1 在面向对象编程中询问位置是不好的做法(讲述而非询问),这可能表明设计决策有问题。 - Stiggler

1
很简单,只需让Cell的构造函数带上它的位置即可,假设这是构造函数:
public:
    Cell(/*assume this is a generic type*/T value, int i, int j)
    {
    }

为什么要这样做?首先,因为创建单元格后,其位置基本上是固定的,除非您进行专门的操作,如“插入”。我不建议在网格上调用方法,或在本地保留网格实例。


为什么您认为位置是固定的?您可能会将单元格拖放到其他位置(甚至在另一个网格上!) - m_pGladiator
我同意"Ion"的观点,我的看法是单元格的位置是固定的,但是单元格的内容是可以改变的。所以,如果你拖放某个东西,你处理的是单元格的内容而不是单元格本身。至少我是这样看的。 - m4design
@m_pGladiator,这就是我说“除非你要插入”的原因。当你拖放时,在大多数情况下,这将是一个插入操作,在某些情况下它将是一个添加操作,或者像M4所说的那样,可能什么都不是,只是一个值的更改。 - user90843
是的,没错,但是单元格是可变的——当移动时,您会修改其内部内容。我想的方式就像拖放实际上将同一单元格对象“重新父化”到另一个网格中,而不会改变单元格的任何值,除了其位置。但是单元格不知道它的位置,因为它由Grid本身管理。 - m_pGladiator

1

最好的方法是向网格询问特定单元格的位置。

另一种解决方案是在单元格的构造函数中为其提供指向网格的指针。当请求单元格的位置时,它可以从网格的函数返回位置。


1

如果您想让单元格知道它的位置,那么只需将其放在单元格内部即可。将其保留在类外部没有意义,因为单个单元格无法在不同的网格中使用(因为您已经想要获取它的位置并且这会限制它的使用)。

或者,如果需要知道位置的单元格方法是从网格中调用的,则可以将位置作为参数传递给该方法。

在某些非常特殊的情况下,您可能会在单元格中存储对网格的引用或将其作为参数传递给其方法,但这感觉不太对,会引入过多的耦合。


1

对于我来说,单元格不需要知道它在网格中的位置似乎并不必要。重要的是,不是单元格从网格获得其位置,而是当需要时网格将位置提供给单元格!因此,网格调用单元格的某个方法来执行此操作。而不是反过来。

最合理的做法是,网格包含许多单元格,因此它“拥有”它们(例如创建单元格,移动它们或其他操作)。因此,单元格不应该知道网格的任何信息。

单元格本身包含一些信息。这些信息可能需要根据网格中的位置进行刷新或进行其他处理。那么,您可以在单元格中拥有一个方法,由网格调用来执行此操作。如果需要,该方法可能会接受位置参数,但单元格本身不将其视为成员。


1

正如Neil所建议的那样,如果单元格需要知道它的位置,它应该将其存储。

话虽如此,我认为单元格不应该需要知道它的位置。网格负责管理单元格,包括它们的位置,告诉它们在哪里绘制等等。单元格应该负责包含什么单元格--例如,数据、格式信息等等。

因此,单元格永远不应该需要知道它在网格中的位置。它可能需要做一些像绘制自己这样的事情,但这应该是通过网格传递的屏幕坐标来完成的。网格应该控制哪些单元格被绘制以及在哪里绘制。单元格应该只做它们被告知要做的事情和位置。


我实际上是按照这个标准设计我的项目的,但我在想,如果单元格保持其位置不变,那么它应该提供显示其位置的方法。网格会知道每个单元格的位置,因为它由许多单元格构成。因此,如果一个网格由cell[5][5]创建,则cell[0][0]将知道它位于网格中的位置(row=0, col=0)。当然,网格也会知道这一点。为了改进设计,我使单元格的位置是恒定的,因此当单元格被构造时,位置从一开始就被固定。我认为这并不是一个可怕的设计。 - m4design

0

网格可以使用某些函数在自身中搜索单元格,该函数可以通过具有缓存或单元格到整数n元组的字典/映射来进行优化。


0

我认为可以将每个单元格对象的位置存储起来,并且网格对象应该包含一个已创建的单元格集合的数量。这样,我将解决一些可能遇到的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接