105
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 设计为私有字段具有类级访问权限而不是对象级访问权限

4

9 回答 9

78

我也有点好奇这个答案。

我找到的最令人满意的答案来自 Artemix 的另一篇文章(我正在用 Person 类重命名 AClass): 为什么使用类级别的访问修饰符而不是对象级别的访问修饰符?

private 修饰符强制执行封装原则。

这个想法是,“外部世界”不应该对 Person 内部流程进行更改,因为 Person 实现可能会随着时间而改变(你必须改变整个外部世界来修复实现中的差异——这几乎是不可能的)。

当 Person 实例访问其他 Person 实例的内部时 - 您可以确定两个实例总是知道 Person 的实现细节。如果 Person 流程的内部逻辑发生了变化,您所要做的就是更改 Person 的代码。

编辑:请投票Artemix 的答案。我只是复制粘贴而已。

于 2013-06-10T15:31:03.413 回答
25

好问题。似乎对象级访问修饰符将进一步执行封装原则。

但实际上情况恰恰相反。让我们举个例子。假设您想在构造函数中深度复制一个对象,如果您无法访问该对象的私有成员。那么唯一可能的方法是向所有私有成员添加一些公共访问器。这将使您的对象对系统的所有其他部分裸露。

所以封装并不意味着对世界其他地方关闭。这意味着要对你想向谁开放。

于 2014-03-07T14:25:13.657 回答
17

请参阅Java 语言规范,第 6.6.1 节。确定可访问性

它指出

否则,如果声明了成员或构造函数private,则当且仅当它出现在包含成员或构造函数声明的顶级类(第 7.6 节)的主体内时,才允许访问。

点击上面的链接了解更多详情。所以答案是:因为 James Gosling 和 Java 的其他作者决定这样做。

于 2013-06-10T15:21:19.407 回答
6

这是有效的,因为你在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-

于 2013-06-10T15:18:34.360 回答
1

关于为什么 Java 中私有可见性的语义是类级别而不是对象级别的问题,我只花了 2 美分。

我想说方便似乎是这里的关键。事实上,在 OP 说明的场景中,对象级别的私有可见性将不得不将方法暴露给其他类(例如,在同一个包中)。

事实上,如果与对象私有级别的可见性相比,我既无法编造也无法找到一个示例,表明类私有级别的可见性(如 Java 提供的)会产生任何问题。

也就是说,具有更细粒度的可见性策略系统的编程语言可以提供对象级别和类级别的对象可见性。

例如Eiffel,提供选择性导出:您可以将任何类特征导出到您选择的任何类,从 {NONE}(对象私有)到 {ANY}(等效于公共,也是默认值)到 {PERSON} (类私有,参见 OP 的示例),到特定的类组 {PERSON, BANK}。

值得注意的是,在 Eiffel 中,您不需要将属性设为私有并编写 getter 来防止其他类分配给它。默认情况下,Eiffel 中的公共属性可在只读模式下访问,因此您不需要 getter 来返回它们的值。

当然,您仍然需要一个 setter 来设置属性,但是您可以通过将其定义为该属性的“分配器”来隐藏它。如果您愿意,这允许您使用更方便的赋值运算符而不是 setter 调用。

于 2017-05-21T07:25:25.983 回答
0

因为private 访问修饰符使它只在中可见。这个方法还在类中。

于 2013-06-10T15:14:43.110 回答
0

private字段可在声明该字段的类/对象中访问。它对于它所在的类/对象之外的其他类/对象是私有的。

于 2013-06-10T15:17:43.283 回答
-1

首先我们必须了解的是,我们要做的就是必须遵循 oops 原则,因此封装就是说将数据包装在包(即类)中,而不是将所有数据表示为对象并且易于访问。因此,如果我们将字段设置为非私有字段,则可以单独访问它。这会导致糟糕的paratice。

于 2016-02-03T11:37:37.120 回答
-2

使用 Java 中的反射概念可以修改字段和方法私有

Modificando metodos y campos privados con Refleccion en Java

于 2014-11-16T04:43:17.210 回答