封装对象应该是公共的还是私有的?

时间:2011-06-09 19:48:22

标签: oop class-design encapsulation

我有点不清楚这个想法是如何让一个类中的所有成员成为私有的,并使公共方法来处理突变。原始类型不是问题,它是我不清楚的封装对象。使对象成员私有的好处是能够隐藏不适用于正在构建的类的上下文的方法。缺点是你必须提供公共方法来将参数传递给底层对象(更多方法,更多工作)。另一方面,如果您希望为底层对象公开所有方法和属性,那么您是否只能将该对象公开? 以这种方式曝光物体会有什么危险?

例如,我发现暴露了矢量或数组列表中的所有内容很有用。我能想到的唯一缺点是,公共成员可能会分配一种类型,而不是通过隐式转换(或某种影响)。一个名义上的指定会减少问题的可能性吗?

只是旁注:我理解真正的封装意味着成员是私人的。

5 个答案:

答案 0 :(得分:2)

  

以这种方式曝光物体会有什么危险?

更改这些对象的类型需要更改类的接口。使用私有对象+公共getter / setter,您只需修改getter和setter中的代码,假设您希望保持返回的内容不变。

请注意,这就是为什么属性在Python等语言中很有用的原因,这些语言在技术上没有私有类成员,最多只有模糊的成员。

答案 1 :(得分:1)

将实例变量公开化的问题在于,您永远不会改变主意,并将它们设为私有,而不会破坏依赖于对这些实例变量的直接公共访问的现有代码。一些例子:

  • 您决定稍后通过同步对实例变量的所有访问来使您的类成为线程安全的,或者通过使用ThreadLocal为每个线程创建值的新副本。如果任何线程可以直接访问变量,则无法执行此操作。

  • 使用向量或数组列表的示例 - 在某些时候,您意识到代码中存在安全漏洞,因为这些类是可变的,因此其他人可以替换列表的内容。如果这只能通过访问器方法获得,您可以通过根据请求创建列表的不可变副本来轻松解决问题,但是您无法使用公共变量执行此操作。

  • 您稍后会意识到,您的某个实例变量是多余的,可以根据其他变量派生。再一次,如果你使用访问器很容易,公共变量是不可能的。

我认为它归结为一个实际的观点 - 如果你知道你是唯一一个将使用这个代码的人,那么你很难编写访问器(每个IDE都会自动为你做这个),并且如果你决定打破API,那么你不介意以后更改你自己的代码,然后去做。但是如果其他人会使用你的课程,或者你想让以后更容易重构以供自己使用,请坚持使用访问器。

答案 2 :(得分:0)

面向对象设计只是一个指导原则。从将要使用你的课程的人的角度来考虑它。平衡OOD,使其直观且易于使用。

答案 3 :(得分:0)

您可能会遇到问题,具体取决于您使用的语言以及它如何处理return语句或赋值运算符。在某些情况下,它可能会为您提供参考,或其他情况下的值。

例如,假设你有一个PrimeCalculator类来计算素数,那么你有另一个类可以用这些素数做一些事情。

public PrimeCalculator calculatorObject = new PrimeCalculator();

Vector<int> primeNumbers = calculatorObject.PrimeNumbersVector;
/* do something complicated here */
primeNumbers.clear(); // free up some memory

当您稍后使用这些内容时,可能在另一个类中,您不希望再次计算数字的开销,因此您使用相同的calculatorObject。

Vector<int> primes = calculatorObject.PrimeNumbersVector;
int tenthPrime = primes.elementAt(9);

此时可能不完全清楚primes和primeNumbers是否引用相同的Vector。如果他们这样做,试图从素数中获得第十个素数会引发错误。

如果您小心并了解您的情况究竟发生了什么,您可以这样做,但是使用函数返回值而不是直接分配变量时,误差较小。

答案 4 :(得分:0)

你可以查看帖子:

first this

then this

这可以解决你的困惑。 它解决了我的问题!感谢Nicol Bolas

另请阅读接受回答下面的评论(另请注意我在第二篇评论中给出的链接(在第一篇文章中))

另请访问the wikipedia post