Unencapsulated means Unchangeable?

Unencapsulated means Unchangeable?

本文关键字:Unchangeable means Unencapsulated      更新时间:2023-10-16

我在有效C++中遇到了这条线:

公开意味着不封闭,而实际上,不封闭意味着不可改变,尤其是用于广泛使用的类。然而,广泛使用的类最需要封装,因为它们是最能从用更好的实现替换一个实现的能力中获益的一个

作者所说的"公开意味着不封闭,而实际上,不封闭意味着不可改变"是什么意思?

未封装的是如何不可更改的?

总体思路很简单。如果你将某个东西公开,那么有人可以也可能会使用它。因此,如果你更改某个公开的东西,所有使用它的代码都会立即中断。破坏人们的密码是不好的;这往往会导致他们不想再使用你的代码,因为现在你强迫他们重写所有的东西,只是因为你想使用不同的类型或其他什么。

公共接口是类的实现和用户之间的契约。更改该契约,尤其是在没有事先通知的情况下,被认为是非常粗鲁的。

如果所有代码都是内部代码,那也没关系。但如果不是这样,如果你正在制作一个库供他人使用(无论是在本地还是只是出售一个库(,那么人们就不太可能对界面的更改感到高兴。

这不是C++规则的问题;这只是一个界面设计规则的问题。由于公共内容是界面的一部分,所以您必须小心公开的内容。

封装是指您只能通过接口方法访问类的数据成员。使用方法的效果是"隐藏"数据成员的实际实现,这样您就可以更改它,而无需通过接口方法更改使用该类的代码(前提是您不更改它们的定义方式(。

另一方面,如果您不使用接口方法来隐藏数据成员实现,那么在数据成员发生任何更改之前,所有使用它的代码都需要进行修改。

假设你有一个类,它有一个包含名称列表的字符串向量。如果你公开了这个向量,那么所有其他类都可以决定直接使用它,并通过向量中的索引来访问它所包含的字符串(比如说,索引充当了识别字符串的键(。

稍后,您可以决定需要一个映射来管理所有这些字符串(您的需求已经改变(。您将数据成员定义更改为映射,代码将不再编译。这就是"实际上不可改变"的含义。

通过封装来管理这一点的"正确"方法是使数据成员私有化,并定义一种接口方法,如:

std::string getStringWithKey(int index);

该方法将在第一种实现中访问向量,在第二种情况中访问映射。所有这些都是以透明的方式进行的:使用该方法(而不是直接访问数据成员(的代码将不需要修改,因此您可以随心所欲地更改数据成员实现,几乎不需要任何成本。

这过于简单化了,因为接口的设计不是一件简单的事情,接口也会发生变化,但我希望这有助于澄清问题。

我想最好的答案将由作者给出。我的猜测是,他的意思是,如果你宣布一个公共成员,并在代码中的许多其他地方使用它,那么如果你后来决定更改该成员,那么更改所有这些地方将是一项艰巨的工作。

他指的是数据成员,他说公开数据成员作为公共接口的一部分意味着你永远不能改变它们的性质,即名称和类型。