3

我有一个关于数据隐藏的 OOP 原则的问题。

据我了解,数据隐藏=将结构的内部字段限制在某个可见区域。动机:如果更改结构内容,则只需更改可见性区域中的实现。

为了强制执行数据隐藏原则,oop 设计者大多决定这样做:

方法一:

封装 = 使可见区域成为结构本身(类),将对其进行操作的函数(方法)放入其中。

这对我来说似乎是一个非常大的要求。并创造了很多不必要的不​​对称。为什么 OOP 设计者不决定以这种方式定义封装:

方法二:

让程序员控制可见区域应该是什么。一个可见区域可能包括多个结构,而不仅仅是一个。在这个可见区域中定义可以在多个结构之间运行的函数。这种方式结构和函数更独立地存在,有更多的对称性,可能需要更少的 getter/setter。

让我举个例子:如果你有一个玻璃物体和一个瓶子物体,里面有一些水。假设您想要实现从瓶子中填充玻璃的能力。

使用方法 1,你被迫做一些不对称的事情,你必须要么实现 glass.fill(bottle) 要么实现 bottle.fill(glass),所以听起来你有一个不必要的困境需要解决。不仅如此,假设你实现了 glass.fill(bottle),现在你在 glass 的范围内,你不能访问瓶子的内部,所以你不得不在瓶子里写一个方法,以便能够更新它。在我看来,这听起来像是很多不必要的工作,而且这种强制的 bottle.update 方法听起来更不利于数据隐藏。

使用方法 2,您可以只定义一个独立的填充(玻璃,瓶子),它可能只知道玻璃和瓶子的内部结构,因为玻璃、瓶子和填充可能是同一可见区域的一部分。听起来是不是容易多了?请注意,您仍然可以使用这种方法定义协议(接口),在外部,您只需要知道玻璃和瓶子是未指定的东西,而填充是对两个东西进行操作的操作:玻璃和瓶子。

我的论点有任何缺陷吗?是否有任何强调这种方法的编程语言尝试?

4

4 回答 4

1

通常,瓶子既不能自动填充玻璃杯,也不能单独填充瓶子。有一个外部协调者负责从瓶子中填充玻璃的过程。

这反映在您提出fill()采用 aGlass g和 a的方法的第二种方法中Bottle b

从 OOAD 的角度来看,您现在需要做的就是 - 创建外部编排器类(也许Person),它将瓶子的内容物倒入玻璃杯中。该fill(Glass g, Bottle b)方法将适当地属于Person该类。

于 2019-07-28T15:02:13.970 回答
0

以您的玻璃和瓶子为例,您希望玻璃响应的信息是“接收此体积的水”;瓶子响应的信息是,“提供这个量的水”。

杯子不需要知道水是从哪里来的,瓶子也不需要知道水去哪里了。玻璃物体需要知道的只是装满它的容量或供应的水量;并且瓶子知道供水直到它是空的或者它收到停止的消息。

因此,玻璃响应“填充”消息的方法签名将是void glass::fill(double volume),而瓶子响应“供应”消息的方法签名将是double bottle::pour()。(可以想象“浇注”和“填充”将逐步进行。)

如您所见,使用这种方法,不需要共享任何内部知识。例如,该glass::fill()方法将一直工作,直到达到其容量等内部不变量,此时它可能会抛出异常“玻璃满”;类似地,该bottle::pour()方法将一直有效,直到瓶子为空,或者捕获到“玻璃满”异常,此时倾倒将停止。

--

我发现许多开发人员错误地认为对象需要始终直接通信。但是,这不是真的;通常,他们会收到“外部宇宙”的快照,作为他们处理的消息的一部分。在上面的示例中,发送到glass对象的快照是在特定时刻倒出的水量(这就是为什么我推断在数字世界中将逐步进行倒水和填充)。

于 2019-07-28T14:46:29.750 回答
0

在这种“哲学”级别的编程语言设计(恕我直言)上确实没有对错。大多数编程语言确实提供了某种程度的“包”可见性,允许一起定义的类以更开放的方式相互访问。

从数据隐藏的角度来看是否fill(Bottle, Glass)有任何优势的问题Bottle::fill(Glass)对我来说是不透明的,但我认为复杂性可以通过两种方式隐藏。我学到的是,拥有依赖关系的有向图总是比循环或双向依赖关系更好。

于 2019-07-27T19:16:40.823 回答
0

您说“方法 2”可能需要“更少的 getter/setter”。这很奇怪,因为“方法 1”应该已经不需要了。如果行为是数据所在的位置,则您不需要“获取”或“设置”事物。

其次,“方法 2”是否“更容易”,或者“方法 1”是否“迫使”你以某种违反直觉的方式做事,这根本不重要。真正重要的是代码是否可以长期维护。是更难写,还是作者不方便都无关紧要,因为更重要的是读者理解它并且更改大部分保持本地化。

这就像马克吐温的名言:“我没有时间写一封短信,所以我写了一封长信。”。编写简单易懂的代码很难。约束,即强迫作者使用某些成语或风格是好的(好吧,假设约束是有意义的)。

于 2019-07-28T14:05:00.700 回答