2011-06-09 69 views
5

我有点不清楚要在将类中的所有成员私人化并采取公共方法处理突变方面采取多大的想法。原始类型不是问题,它是我不清楚的封装对象。使对象成员变为私有的好处是能够隐藏不适用于正在构建的类的上下文的方法。缺点是你必须提供公共方法来传递参数给底层对象(更多的方法,更多的工作)。在其他方面,如果你想让所有的方法和属性暴露给底层对象,你能不能公开对象? 以这种方式暴露对象有什么危险?环保对象应该公开还是私密?

例如,我会发现将矢量或数组列表中的所有内容都暴露出来会很有用。我能想到的唯一缺点是,公共成员可能会通过隐式转换(或其他影响)来分配类型。是否能够减少潜在的问题?

只是一个侧面说明:我明白,真正的诠释意味着成员是私人的。

+0

见迪米特法则http://en.wikipedia.org/wiki/Law_of_Demeter,在OOP语言中,您应该尽量减少依赖关系。 这取决于“类”是否真正具有功能,或者实际上是数据结构。如果它只是一个数据结构,那么getters'n'setter看起来有点过分,特别是如果所有的字段都是不可变的(final)。 – earcam 2011-07-02 19:05:20

回答

2

以这种方式暴露对象有什么危险?

更改这些对象的类型需要将接口更改为类。使用私有对象+公共getter/setter,只需要修改getter和setter中的代码,假设你想保持返回的东西一样。

请注意,这就是为什么属性在诸如Python之类的语言中很有用,因为它在技术上没有私有类成员,最多只能隐藏类成员。

+1

但你不觉得这是宣布'私人对象+ public getters/setters'的结果吗?如果他宣布一切公开?虽然由于其他许多原因,我不建议这样做,但我不认为这个答案证明 – 2011-07-02 05:27:03

+0

这个问题是正确的,“如果他宣布一切公开,该怎么办?”然后没有封装,并且改变直接暴露的类的成员将需要改变访问直接暴露的成员并期望它以某种方式行为的任何东西。你正在考虑这个问题。 – JAB 2011-07-05 13:39:24

0

面向对象的设计只是一个指导原则。从使用你班级的人的角度思考它。平衡OOD,使其直观易用。

+0

好吧。那么你会希望你的命名约定与该类的设计保持一致。所以,如果你有一个公开的整数向量来保存素数,我想这可能是一个糟糕的形式,给一个像“PrimeVector” – 2011-06-09 20:02:44

+0

这样的名字显然你想称之为“VectorPrime”。 – JAB 2011-06-09 20:08:35

+1

这么多基于你手头任务的细节。例如,如果我们正在谈论Java,其中Vector是一个众所周知的类,并且您正在设计Java程序所使用的类,那么我的首选是将它命名为“PrimeNumbers”以及类型向量。如果您使用的语言不同,您将自己的类命名为Vector,则还需要在界面中公开该类。如果你正在做一个非强类型的接口,我会称之为“PrimeNumbersVector”。另外,如果您正在编写COM接口,还有其他注意事项。 – 2011-06-09 20:18:33

1

使实例变量公开的问题是,你以后永远不会改变主意,并且使它们变为私有的,而不会破坏依赖于直接公共访问这些实例变量的现有代码。一些例子:

  • 您决定以后让你的类线程安全的增值经销商,或可能通过使用一个ThreadLocal创建每个线程的值的新副本同步所有访问实例。如果任何线程可以直接访问变量,就不能这样做。

  • 使用你的向量或数组列表的例子 - 在某些时候,你意识到在你的代码中存在一个安全缺陷,因为这些类是可变的,所以其他人可以替换列表的内容。如果这只能通过访问方法获得,你可以根据请求通过创建一个不可变的副本来轻松解决问题,但不能用公共变量来实现。

  • 稍后您会意识到,您的一个实例变量是多余的,可以基于其他变量派生。如果您使用访问器,再次轻松,使用公共变量不可能。

我认为它归结为一个实用的点 - 如果你知道你是谁将会使用这个代码只有一个,而它的痛苦,你写的访问器(每个IDE会为你做它自动),并且如果您决定中断API,则不介意稍后更改自己的代码,然后继续。但是如果其他人将会使用你的班级,或者如果你希望稍后为了自己的使用而重构,可以使用访问器。

0

您可能遇到的问题取决于您使用的语言以及它如何处理返回语句或赋值运算符。在某些情况下,它可能会给你一个参考,或在其他情况下的值。例如,假设你有一个计算素数的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。如果他们这样做,试图从素数中获得第十个素数将会导致错误。

如果您仔细了解并了解您的情况到底发生了什么,但是您使用函数返回值而不是直接分配变量的误差范围更小,您可以这样做。

0

那么你可以检查后:

first this

then this

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

而且阅读接受的答案(也注意到由我(在倒数第二个评论中给出的链接中的第一篇文章))

下面的评论中也可以访问the wikipedia post

相关问题