访问同一类中另一个对象的私有字段

时间:2021-02-19 18:08:50
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;
   }
}

Please forget about the design. I know that OOP specifies that private objects are private to the class. My question is, why was OOP designed such that private fields have class-level access and not object-level access?

请忘掉设计。我知道OOP指定私有对象是类的私有对象。我的问题是,为什么OOP设计成私有字段具有类级访问而非对象级访问?

10 个解决方案

#1


44  

I am also a bit curious with the answer.

我对这个答案也有点好奇。

The most satisfying answer that I find is from Artemix in another post here (I'm renaming the AClass with Person class): Why have class-level access modifiers instead of object-level?

我找到的最令人满意的答案是在这里的另一个帖子中(我正在用Person类重新命名AClass):为什么要使用类级别的访问修饰符而不是对象级别?

The private modifier enforces Encapsulation principle.

私有修改器执行封装原则。

The idea is that 'outer world' should not make changes to Person internal processes because Person implementation may change over time (and you would have to change the whole outer world to fix the differences in implementation - which is nearly to impossible).

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

When instance of Person accesses internals of other Person instance - you can be sure that both instances always know the details of implementation of Person. If the logic of internal to Person processes is changed - all you have to do is change the code of Person.

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

EDIT: Please upvote Artemix' answer. I'm just copy-pasting it.

编辑:请投票给阿特米九的答案。我只是复制粘贴。

#2


15  

See the Java Language Specification, Section 6.6.1. Determining Accessibility

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

It states

它的州

Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.

否则,如果成员或构造函数声明私有,那么访问允许当且仅当它发生在身体的*类(§7.6)包含成员或声明的构造函数。

Click the link above for more details. So the answer is: Because James Gosling and the other authors of Java decided it to be that way.

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

#3


5  

Good question. It seems that object level access modifier would enforce the Encapsulation principle even further.

好问题。似乎对象级访问修饰符会进一步加强封装原则。

But actually it's the other way around. Let's take an example. Suppose you want to deep copy an object in a constructor, if you cannot access the private members of that object. Then the only possible way is to add some public accessors to all of the private members. This will make your objects naked to all other parts of the system.

但实际上是反过来的。让我们看一个例子。假设您想要在构造函数中深度复制一个对象,如果您不能访问该对象的私有成员。然后,唯一可能的方法是向所有的私有成员添加一些公共访问器。这将使您的对象对系统的所有其他部分都是赤裸的。

So encapsulation doesn't mean being closed to all of the rest of the world. It means being selective about whom you want to be open to.

所以封装并不意味着要对世界其他地方关闭。这意味着你要有选择性地向你敞开心扉。

#4


2  

This works because you are in the class Person - a class is allowed to poke inside it's own type of class. This really helps when you want to write a copy constructor, for example:

这之所以有效,是因为您是类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; }
};

Or if we want to write operator+ and operator- for our big number class.

或者如果我们想写运算符+和运算符-对于大数类。

#5


0  

Because the private access modifier renders it visible only within the class. This method is still IN the class.

因为私有访问修饰符只在类中显示它。这个方法仍然在类中。

#6


0  

the private field is accessible in the class/object in which the field is declared. It is private to other classes/objects outside of the one it is located in.

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

#7


0  

With reflection concept in Java is possible modify fields and methods privates

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

Modificando metodos y campos privados con Refleccion en Java

在爪哇岛,你可以买到更多的东西

#8


0  

First thing here we have to understand is all we have to do is must follow oops principles so encapsulation is say that wrap data within package(i.e. class) and than represent all data as Object and easy to access. so if we make field as non-private than it's accessed indivisually. and it result into bad paratice.

这里我们首先要理解的是,我们所要做的就是遵循oops原则,所以封装就是将数据封装在包中(例如。类),而不是表示所有数据为对象,易于访问。因此,如果我们将字段设置为非私有的,而不是不可访问的。这导致了糟糕的合作。

#9


0  

Just my 2 cents on the question of why the semantics of the private visibility in Java is class level rather than object level.

关于为什么Java中私有可见性的语义是类级别而不是对象级别的问题,我只想说两点。

I would say that convenience seems to be the key here. In fact, a private visibility at object level would have forced to expose methods to other classes (e.g. in the same package) in the scenario illustrated by the OP.

我想说,便利似乎是关键。事实上,在对象级别上的私有可见性会迫使将方法公开给OP描述的场景中的其他类(例如在同一个包中)。

In truth I was not able neither to concoct nor to find an example showing that the visibility at class-private level (like offered by Java) creates any issues if compared to visibility at object-private level.

事实上,我既不能捏造也不能找到一个例子来说明类-私有级别的可见性(如Java提供的)与对象-私有级别的可见性相比会产生任何问题。

That said, programming languages with a more fine-grained system of visibility policies can afford both object visibility at object level and class level.

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

For example Eiffel, offers selective export: you can export any class feature to any class of your choice, from {NONE} (object-private) to {ANY} (the equivalent of public, and also the default), to {PERSON} (class-private, see the OP's example), to specific groups of classes {PERSON, BANK}.

例如,Eiffel提供了选择性导出:您可以将任何类特性导出到您选择的任何类,从{NONE} (object-private)到{any} (public的等效项,也是默认项),到{PERSON} (class-private,参见OP的示例),再到特定的类组{PERSON, BANK}。

It's also interesting to remark that in Eiffel you don't need to make an attribute private and write a getter to prevent other classes from assigning to it. Public attributes in Eiffel are by default accessible in read-only mode, so you don't need a getter just to return their value.

同样有趣的是,在Eiffel中您不需要将属性设置为private并编写一个getter来阻止其他类为其赋值。Eiffel中的公共属性在只读模式下是可访问的,所以您不需要一个getter来返回它们的值。

Of course you still need a setter to set an attribute, but you can hide it by defining it as "assigner" for that attribute. This allows you, if you wish, to use the more convenient assignment operator instead of the setter invocation.

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

#10


-1  

Private in java is class level access as you wrote. Scala has also object private written as private[this] and other various ways detailed here http://alvinalexander.com/scala/how-to-control-scala-method-scope-object-private-package

java中的Private是类级访问。Scala还将对象私有写成private[this],并通过各种方式详细介绍http://alvinalexander.com/scala/how- control- Scala -method-scope-object-private包

Most probably private class level access in java was considered enough and is in sync with what c++ had at that moment.

最可能的是,java中的私有类级别访问已经足够,并且与c++当时的访问同步。

I assume this was enough in java because a class was written in a single file so an author could decide to access members between different instances if it really wanted to. In scala you can inherit behavior from multiple traits and this might change the game.

我认为这在java中已经足够了,因为一个类是在一个文件中编写的,所以如果需要的话,作者可以决定访问不同实例之间的成员。在scala中,您可以从多个特性继承行为,这可能会改变游戏。

#1


44  

I am also a bit curious with the answer.

我对这个答案也有点好奇。

The most satisfying answer that I find is from Artemix in another post here (I'm renaming the AClass with Person class): Why have class-level access modifiers instead of object-level?

我找到的最令人满意的答案是在这里的另一个帖子中(我正在用Person类重新命名AClass):为什么要使用类级别的访问修饰符而不是对象级别?

The private modifier enforces Encapsulation principle.

私有修改器执行封装原则。

The idea is that 'outer world' should not make changes to Person internal processes because Person implementation may change over time (and you would have to change the whole outer world to fix the differences in implementation - which is nearly to impossible).

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

When instance of Person accesses internals of other Person instance - you can be sure that both instances always know the details of implementation of Person. If the logic of internal to Person processes is changed - all you have to do is change the code of Person.

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

EDIT: Please upvote Artemix' answer. I'm just copy-pasting it.

编辑:请投票给阿特米九的答案。我只是复制粘贴。

#2


15  

See the Java Language Specification, Section 6.6.1. Determining Accessibility

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

It states

它的州

Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.

否则,如果成员或构造函数声明私有,那么访问允许当且仅当它发生在身体的*类(§7.6)包含成员或声明的构造函数。

Click the link above for more details. So the answer is: Because James Gosling and the other authors of Java decided it to be that way.

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

#3


5  

Good question. It seems that object level access modifier would enforce the Encapsulation principle even further.

好问题。似乎对象级访问修饰符会进一步加强封装原则。

But actually it's the other way around. Let's take an example. Suppose you want to deep copy an object in a constructor, if you cannot access the private members of that object. Then the only possible way is to add some public accessors to all of the private members. This will make your objects naked to all other parts of the system.

但实际上是反过来的。让我们看一个例子。假设您想要在构造函数中深度复制一个对象,如果您不能访问该对象的私有成员。然后,唯一可能的方法是向所有的私有成员添加一些公共访问器。这将使您的对象对系统的所有其他部分都是赤裸的。

So encapsulation doesn't mean being closed to all of the rest of the world. It means being selective about whom you want to be open to.

所以封装并不意味着要对世界其他地方关闭。这意味着你要有选择性地向你敞开心扉。

#4


2  

This works because you are in the class Person - a class is allowed to poke inside it's own type of class. This really helps when you want to write a copy constructor, for example:

这之所以有效,是因为您是类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; }
};

Or if we want to write operator+ and operator- for our big number class.

或者如果我们想写运算符+和运算符-对于大数类。

#5


0  

Because the private access modifier renders it visible only within the class. This method is still IN the class.

因为私有访问修饰符只在类中显示它。这个方法仍然在类中。

#6


0  

the private field is accessible in the class/object in which the field is declared. It is private to other classes/objects outside of the one it is located in.

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

#7


0  

With reflection concept in Java is possible modify fields and methods privates

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

Modificando metodos y campos privados con Refleccion en Java

在爪哇岛,你可以买到更多的东西

#8


0  

First thing here we have to understand is all we have to do is must follow oops principles so encapsulation is say that wrap data within package(i.e. class) and than represent all data as Object and easy to access. so if we make field as non-private than it's accessed indivisually. and it result into bad paratice.

这里我们首先要理解的是,我们所要做的就是遵循oops原则,所以封装就是将数据封装在包中(例如。类),而不是表示所有数据为对象,易于访问。因此,如果我们将字段设置为非私有的,而不是不可访问的。这导致了糟糕的合作。

#9


0  

Just my 2 cents on the question of why the semantics of the private visibility in Java is class level rather than object level.

关于为什么Java中私有可见性的语义是类级别而不是对象级别的问题,我只想说两点。

I would say that convenience seems to be the key here. In fact, a private visibility at object level would have forced to expose methods to other classes (e.g. in the same package) in the scenario illustrated by the OP.

我想说,便利似乎是关键。事实上,在对象级别上的私有可见性会迫使将方法公开给OP描述的场景中的其他类(例如在同一个包中)。

In truth I was not able neither to concoct nor to find an example showing that the visibility at class-private level (like offered by Java) creates any issues if compared to visibility at object-private level.

事实上,我既不能捏造也不能找到一个例子来说明类-私有级别的可见性(如Java提供的)与对象-私有级别的可见性相比会产生任何问题。

That said, programming languages with a more fine-grained system of visibility policies can afford both object visibility at object level and class level.

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

For example Eiffel, offers selective export: you can export any class feature to any class of your choice, from {NONE} (object-private) to {ANY} (the equivalent of public, and also the default), to {PERSON} (class-private, see the OP's example), to specific groups of classes {PERSON, BANK}.

例如,Eiffel提供了选择性导出:您可以将任何类特性导出到您选择的任何类,从{NONE} (object-private)到{any} (public的等效项,也是默认项),到{PERSON} (class-private,参见OP的示例),再到特定的类组{PERSON, BANK}。

It's also interesting to remark that in Eiffel you don't need to make an attribute private and write a getter to prevent other classes from assigning to it. Public attributes in Eiffel are by default accessible in read-only mode, so you don't need a getter just to return their value.

同样有趣的是,在Eiffel中您不需要将属性设置为private并编写一个getter来阻止其他类为其赋值。Eiffel中的公共属性在只读模式下是可访问的,所以您不需要一个getter来返回它们的值。

Of course you still need a setter to set an attribute, but you can hide it by defining it as "assigner" for that attribute. This allows you, if you wish, to use the more convenient assignment operator instead of the setter invocation.

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

#10


-1  

Private in java is class level access as you wrote. Scala has also object private written as private[this] and other various ways detailed here http://alvinalexander.com/scala/how-to-control-scala-method-scope-object-private-package

java中的Private是类级访问。Scala还将对象私有写成private[this],并通过各种方式详细介绍http://alvinalexander.com/scala/how- control- Scala -method-scope-object-private包

Most probably private class level access in java was considered enough and is in sync with what c++ had at that moment.

最可能的是,java中的私有类级别访问已经足够,并且与c++当时的访问同步。

I assume this was enough in java because a class was written in a single file so an author could decide to access members between different instances if it really wanted to. In scala you can inherit behavior from multiple traits and this might change the game.

我认为这在java中已经足够了,因为一个类是在一个文件中编写的,所以如果需要的话,作者可以决定访问不同实例之间的成员。在scala中,您可以从多个特性继承行为,这可能会改变游戏。