Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 电子封装的对象应该是公共的还是私有的?_Oop_Class Design_Encapsulation - Fatal编程技术网

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

Oop 电子封装的对象应该是公共的还是私有的?,oop,class-design,encapsulation,Oop,Class Design,Encapsulation,我有点不清楚在将类中的所有成员私有化和将处理突变的方法公开化的过程中该走多远。基本类型不是问题所在,它是我不清楚的封装对象。使对象成员私有的好处是能够隐藏不适用于所构建类上下文的方法。缺点是必须提供公共方法来将参数传递给底层对象(方法越多,工作量越大)。另一方面,如果您想为底层对象公开所有方法和属性,您不能将对象公开吗以这种方式暴露物体有什么危险? 例如,我发现公开向量或数组列表中的所有内容非常有用。我能想到的唯一缺点是,公共成员可以潜在地分配一个类型,而不是通过隐式转换(或类似的方式)。自愿指

我有点不清楚在将类中的所有成员私有化和将处理突变的方法公开化的过程中该走多远。基本类型不是问题所在,它是我不清楚的封装对象。使对象成员私有的好处是能够隐藏不适用于所构建类上下文的方法。缺点是必须提供公共方法来将参数传递给底层对象(方法越多,工作量越大)。另一方面,如果您想为底层对象公开所有方法和属性,您不能将对象公开吗以这种方式暴露物体有什么危险?

例如,我发现公开向量或数组列表中的所有内容非常有用。我能想到的唯一缺点是,公共成员可以潜在地分配一个类型,而不是通过隐式转换(或类似的方式)。自愿指定是否会减少出现问题的可能性

只需补充说明:我理解真正的授权意味着成员是私有的

以这种方式暴露物体有什么危险

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


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

面向对象设计只是一个指南。从将使用您的类的人的角度考虑。在OOD与直观性和易用性之间取得平衡。

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

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

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

  • 稍后您会意识到您的一个实例变量是冗余的,可以基于其他变量派生。同样,如果您使用的是访问器,那么这很容易,而使用公共变量则不可能


我认为这可以归结为一个实际问题——如果您知道您是唯一一个使用此代码的人,并且编写访问器(每个IDE都会自动为您完成)会让您感到痛苦,并且如果您决定破坏API,您不介意稍后更改您自己的代码,那么就开始吧。但是,如果其他人将使用您的类,或者如果您希望以后更易于重构供自己使用,请坚持使用访问器。

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

例如,假设您有一个计算素数的PrimeCalculator类,然后您有另一个处理这些素数的类

public PrimeCalculator calculatorObject = new PrimeCalculator();

Vector<int> primeNumbers = calculatorObject.PrimeNumbersVector;
/* do something complicated here */
primeNumbers.clear(); // free up some memory
public PrimeCalculator calculator object=new PrimeCalculator();
向量素数=计算器对象。素数向量;
/*在这里做些复杂的事情*/
素数。清除();//释放一些内存
当您稍后使用这些东西时,可能在另一个类中,您不希望再次计算数字的开销,因此您使用相同的calculatorObject

Vector<int> primes = calculatorObject.PrimeNumbersVector;
int tenthPrime = primes.elementAt(9);
向量素数=计算器对象。素数向量; int tenthPrime=primes.elementAt(9); 现在可能不太清楚素数和素数是否引用同一个向量。如果他们这样做,试图从素数中得到第十个素数将抛出一个错误


如果你很仔细,并且理解了你的情况下到底发生了什么,你可以这样做,但是使用函数返回一个值而不是直接分配变量,你的误差幅度会更小。

你可以查看帖子:

这会解决你的困惑<它解决了我的问题!感谢。

也请阅读接受答案下方的评论(请注意我在最后一条评论中给出的链接(在第一篇文章中))


也请访问

Well-put。然后,您希望您的命名约定与类的to设计保持一致。所以,如果你有一个整数的公共向量,用来保存素数,我想给它起个像“素数向量”这样的名字是很糟糕的,很明显你会把它叫做“向量素数”。这是基于你手头任务的细节。例如,如果我们讨论的是Java,其中Vector是一个众所周知的类,并且您正在设计Java程序所使用的类,那么我倾向于将它命名为类似“素数”的东西,并且是Vector类型。如果您使用的是另一种语言,并且您使用了自己的名为Vector的类,那么还需要在接口中公开该类。如果你在做一个非强类型的接口,我会称之为“PrimeNumbersVector”。此外,如果您正在编写COM接口,还需要考虑其他因素。@JAB如果有Optimus类就好了。;-)Brighwell-Uptick用于COM引用。但是您不认为这是声明
私有对象的结果吗