class Person
{
private BankAccount account;
Person(BankAccount account)
{
this.account = account;
}
public Person someMethod(Person person)
{
//Why accessing private field is possible?
BankAccount a = person.account;
}
}
请忘记设计。我知道OOP指定私有对象是该类的私有对象。我的问题是,为什么OOP设计为私有字段具有类级访问权限和不是对象级访问?
答案 0 :(得分:48)
我对答案也有点好奇。
我找到的最令人满意的答案是来自Artemix的另一篇文章(我用Person类重命名了AClass): Why have class-level access modifiers instead of object-level?
私有修饰符强制执行封装原则。
这个想法是'外部世界'不应该对Person内部流程进行更改,因为Person实现可能会随着时间的推移而发生变化(并且您必须更改整个外部世界以修复实现中的差异 - 这几乎是不可能的)
当Person的实例访问其他Person实例的内部时 - 您可以确保两个实例始终知道Person的实现细节。如果Person流程内部的逻辑发生了变化 - 您所要做的就是更改Person的代码。
编辑: 请投票 Artemix'回答。我只是复制粘贴它。
答案 1 :(得分:16)
请参阅Java Language Specification, Section 6.6.1. Determining Accessibility
说明
否则,如果成员或构造函数被声明为
private
,那么 当且仅当它发生在主体内时才允许访问 顶级类(第7.6节),包含成员或的声明 构造
点击上面的链接了解更多详情。所以答案是:因为James Gosling和Java的其他作者决定它是这样的。
答案 2 :(得分:8)
好问题。似乎对象级访问修饰符将进一步强制执行封装原则。
但实际上它是另一种方式。我们来举个例子吧。假设您要在构造函数中深层复制对象,如果您无法访问该对象的私有成员。然后唯一可能的方法是向所有私有成员添加一些公共访问者。这将使您的对象裸到系统的所有其他部分。
所以封装并不意味着对世界其他所有国家都是封闭的。这意味着选择你想要对谁开放。
答案 3 :(得分:2)
这是有效的,因为你在class Person
- 允许一个类在它自己的类中捅。当您想要编写复制构造函数时,这确实很有用,例如:
class A
{
private:
int x;
int y;
public:
A(int a, int b) x(a), y(b) {}
A(A a) { x = a.x; y = y.x; }
};
或者,如果我们想为我们的大号班写operator+
和operator-
。
答案 4 :(得分:0)
因为private
访问修饰符仅在类中呈现它。此方法仍属于班级。
答案 5 :(得分:0)
可以在声明字段的类/对象中访问private
字段。它对于其所在的其他类/对象是私有的。
答案 6 :(得分:0)
使用Java中的反射概念可以修改字段和方法privates
Modificando metodos y campos privados con Refleccion en Java
答案 7 :(得分:0)
我们必须要了解的第一件事就是我们所要做的就是必须遵循oops原则,所以封装就是说将数据包装在包(即类)中,而不是将所有数据表示为Object并且易于访问。 / strong>所以如果我们将字段设为非私有字段 它是单独访问的。这导致了糟糕的生活。
答案 8 :(得分:0)
关于为什么Java中私有可见性的语义是类级别而不是对象级别的问题,我只花了2美分。
我会说便利性似乎是关键所在。实际上,对象级别的私有可见性将被迫在OP所示的场景中将方法暴露给其他类(例如,在同一个包中)。
事实上,我无法编造或找到一个示例,表明如果与对象 - 私有级别的可见性相比,类 - 私有级别(如Java提供的)的可见性会产生任何问题。
也就是说,具有更细粒度的可见性策略系统的编程语言可以在对象级别和类级别上提供对象可见性。
例如Eiffel,提供选择性导出:您可以将任何类功能导出到您选择的任何类,从{NONE}(object-private)到{ANY}(相当于public,以及默认),{PERSON}(class-private,参见OP的例子),特定的类组{PERSON,BANK}。
有趣的是,在Eiffel中,您不需要将属性设为私有,而是编写一个getter来防止其他类分配给它。默认情况下,Eiffel中的公共属性是以只读模式访问的,因此您不需要getter来返回它们的值。
当然,您仍然需要一个setter来设置属性,但您可以通过将其定义为该属性的“assigner”来隐藏它。如果您愿意,这允许您使用更方便的赋值运算符而不是setter调用。
答案 9 :(得分:-1)
java中的Private是您编写的类级访问。
Scala还将私有对象写为private[this]
以及此处详述的其他各种方式http://alvinalexander.com/scala/how-to-control-scala-method-scope-object-private-package
很可能java中的私有类级别访问被认为是足够的,并且与当时的c ++有同步。
我认为这在java中已经足够了,因为一个类是在一个文件中编写的,因此作者可以决定在不同实例之间访问成员,如果它真的想要的话。在scala中,您可以从多个特征继承行为,这可能会改变游戏。