数据抽象和封装的好处
Data abstraction and encapsulation benefits
我有两点要问并得到解决(来自C++ Primer):
1: Class internals are protected from inadvertent user-level errors,
which might corrupt the state of the object.
2: The class implementation may evolve over time in response to changing
requirements or bug reports without requiring change in user-level
code.
现在,对于第一点,我可以想到 cin
或任何其他 I/O 对象,其状态可能会因数据错误而损坏,但我仍然不明白 class 内部保护。第二点我完全不清楚。
每个 class(极少数例外)都有一个开放的接口和一个封闭的实现。
这允许在不更改开放接口的情况下更改实现。
因此 class 的用户无需在实施更改时更改其代码。
相对于标准 class std::cin
那么它没有损坏,那么用户输入了错误的数据。其内部状态稳定。它只是为用户设置一个错误标志,以通知他们他们做错了什么。
关键是对对象的任何访问都必须通过应该以安全方式定义的 public 接口(将其视为对象内部的一种防火墙).
这是设计方面的问题。对象应具有 well-defined 角色(通过 public 接口公开)。这些角色在软件发展过程中应该很少(如果有的话)改变。由于各种原因(bugs/optimizations/etc.),内部实现可能会发生变化,但只要接口保持不变,软件就应该继续工作而无需更改其他模块。封装是使软件模块化的好方法。
该语句在非常普遍的意义上使用了"corrupt the state",即成员变量的值偏离了使用它们的方法的预期。考虑一个不是 public 的成员变量:您在构造函数中设置它,然后在成员函数中修改它。因此,无论成员变量有什么值,它都是由您的代码单独分配的。假设您的代码是正确的,变量的状态始终是您的代码所期望的状态。另一方面,Public 成员变量可以通过使用您的 class 的代码进行更改。每次您的代码引用此类变量时,它都冒着找到其他人代码设置的值的风险。在并非所有可能的值都被认为是正确的情况下,您的成员函数必须假定 public 成员变量中的值无效。
这是一种说法,如果你决定改变一个成员变量的意义,用新的成员变量替换它,或者从实现中删除它,你只能这样做,只要因为变量是私有的。 Public 成员变量不提供这种保护,因为如果重命名或删除它们,使用它们的外部代码将停止编译。当您决定更改变量的含义而不重命名它时,会发生更糟糕的情况。在这种情况下,外部代码仍然可以编译,但您的代码最终会出现损坏状态,如上面#1 中所述。
我有两点要问并得到解决(来自C++ Primer):
1: Class internals are protected from inadvertent user-level errors, which might corrupt the state of the object.
2: The class implementation may evolve over time in response to changing requirements or bug reports without requiring change in user-level code.
现在,对于第一点,我可以想到 cin
或任何其他 I/O 对象,其状态可能会因数据错误而损坏,但我仍然不明白 class 内部保护。第二点我完全不清楚。
每个 class(极少数例外)都有一个开放的接口和一个封闭的实现。
这允许在不更改开放接口的情况下更改实现。
因此 class 的用户无需在实施更改时更改其代码。
相对于标准 class std::cin
那么它没有损坏,那么用户输入了错误的数据。其内部状态稳定。它只是为用户设置一个错误标志,以通知他们他们做错了什么。
关键是对对象的任何访问都必须通过应该以安全方式定义的 public 接口(将其视为对象内部的一种防火墙).
这是设计方面的问题。对象应具有 well-defined 角色(通过 public 接口公开)。这些角色在软件发展过程中应该很少(如果有的话)改变。由于各种原因(bugs/optimizations/etc.),内部实现可能会发生变化,但只要接口保持不变,软件就应该继续工作而无需更改其他模块。封装是使软件模块化的好方法。
该语句在非常普遍的意义上使用了"corrupt the state",即成员变量的值偏离了使用它们的方法的预期。考虑一个不是 public 的成员变量:您在构造函数中设置它,然后在成员函数中修改它。因此,无论成员变量有什么值,它都是由您的代码单独分配的。假设您的代码是正确的,变量的状态始终是您的代码所期望的状态。另一方面,Public 成员变量可以通过使用您的 class 的代码进行更改。每次您的代码引用此类变量时,它都冒着找到其他人代码设置的值的风险。在并非所有可能的值都被认为是正确的情况下,您的成员函数必须假定 public 成员变量中的值无效。
这是一种说法,如果你决定改变一个成员变量的意义,用新的成员变量替换它,或者从实现中删除它,你只能这样做,只要因为变量是私有的。 Public 成员变量不提供这种保护,因为如果重命名或删除它们,使用它们的外部代码将停止编译。当您决定更改变量的含义而不重命名它时,会发生更糟糕的情况。在这种情况下,外部代码仍然可以编译,但您的代码最终会出现损坏状态,如上面#1 中所述。