Why different objects of the same class can access private fields from one another?

5

Today while I was doing a course in Udacity (Intro to Java Programming) I thought about this in the Update the class Person exercise (lesson 3 29/45).

In object-oriented modeling we have the concept of encapsulation (hide implementation) that has no direct relation to protection, but noting one of the purposes of OOP is to provide modeling closer to the organization in the real world, why John can read the "thoughts" of Mary and not ask her?

Class example

class Pessoa {
    // Pensamentos sao privados
    private List<String> pensamentos;

    public void lePensamentos(Pessoa outraPessoa) {
         // Por que uma pessoa pode ler os pensamentos de outra pessoa?
         System.out.println(outraPessoa.pensamentos);
    }
}

Example of "undue" access to the thoughts of another object

Pessoa joao = new Pessoa();
Pessoa maria = new Pessoa();

//João é um objeto em um mundo virtual que representa uma pessoa e seu comportamento deve ser como esperado no mundo real!
//João está curioso para saber o que Maria está pensando então ele chama um método para acabar com sua curiosidade
maria.fazPergunta("O que você está pensando Maria?");

//João percebe que ela não quis responder e achou uma solução! Acessar diretamente seus pensamentos (superpoderes!)
joao.lePensamentos(maria); // isso funciona!

Does the Java language provide any protection feature? In Java we have the ability to isolate parts of memory for security reasons? (This question is only for reflection or extra comment)

Clarifications

  • The example demonstrates situations in which joão (instance) accesses Mary attributes / fields that should be private only to her.
  • The word "private" is more in another context than access modifiers in Java, here I put this word as if it were "something private" that only the instance should have direct access other attributes also as an attribute that holds someone's "password", etc.).
  • So I asked the question if in Java we have the ability to isolate parts of memory for security reasons.

        
    asked by anonymous 26.08.2016 / 14:09

    4 answers

    7

    The example question does not show what was asked.

    TL; DR

    The simple answer to the question is why the designers of the language wanted so and it was specified this . C ++ did so, C # also.

    Justification

    One justification for choosing this is that the compiler is analyzing code that is not running. He does not look at objects, he just looks at what's in the class. It has no way to guarantee that the object that is there is a different object from the current one. It may be the current one.

    Of course you could adopt a convention that if the object does not come with the implicit parameter this , which every instance method has, then it should be considered an object other than the current one. But that would complicate some usage patterns. What you are receiving may not even be the object of this class, but rather an instance of a derivative.

    A good example

    How would you do a equals() between two objects of the same class, one of them is the parameter this implicit and another could be a parâmetro explícito that '? It is common for the equality method to access private members to verify equality.

    public boolean equals(Pessoa that) {
        return this.nome.equals(that.nome); //considero que nome é privado
    }
    

    Then you should ask yourself what would be the gain of blocking this. The private member is not a data access protection mechanism. It's just a way to make it easier for code to not see members who depend on implementation detail, it's not something that goes for security.

    Encapsulation

    If the implementation detail changes, the class itself has changed. All class code should be aware of the change. The engine does not want to save the programmer from inadvertently making any changes to the class, otherwise the code will be too rigid. This exists only to prevent external access to the class from making some access. This access is internal.

    Used for encapsulation, which refers to the class and not the object. Any object of this class is "trusted" from a code point of view.

    Of course, some language may give you the option to restrict this, after all it has its usefulness, as Scala does (see Anthony Accioly's comment).

    Conclusion

    So understand is not to protect access to the object , it's to ensure internal visibility in class . It's not a security mechanism, it's just conceptual. Remember that any object can be accessed from anywhere by various techniques, more or less sophisticated, that pass over the compiler, for example with reflection.

        
    26.08.2016 / 15:04
    5

    As you yourself mentioned guiwp, based on the SO response in English on this link here :

    The private member of a class is intended to encapsulate code. This serves both to maintain the organization and to prevent external agents from modifying it unexpectedly.

    As in the example (copied to the code snippet below to facilitate) the class handles an instance of itself. This does not break the encapsulation rule that causes it to be protected from external agents because the class has knowledge about how to "deal" with the information contained in it.

    public class Foo {
      private int secret;
      public void bar(final Foo foo) {
        foo.secret = 100;
      }
    }
    

    If the situation were: class Bar attempts to change Foo's private member an error would be triggered.

    As Foo changes an instance of Foo (an instance of the same class) internally Java (as other languages do as well) understands it as normal behavior.

    I hope I have been able to help.

        
    26.08.2016 / 14:36
    2

    Because the purpose of access control levels is not this.

    The idea of encapsulation is to ensure that your classes can not suffer harmful interference from other classes.

    That is, if you designed class X to solve problem Y, you do not want your neighbor to design a class Z that uses its class X in a totally inadequate way and end up breaking with the premises that functioning properly. With this access control, it's much easier to develop robust, secure, well-testable, and more stupid-proof code thanks to the encapsulation.

    The idea is to expose the other classes, which may have been designed by different people, only valid forms that make sense to interact with it. To get a fairly beaten concrete example, imagine the String class. It has a private field of type char[] (in OpenJDK 8), and so a String can be used safely and that makes sense, you will not want the class Gambiarra123 than your nephew's nephew invented it to end up messing with the% s of the entire system for some stupid reason.

    From this concept of exposing only what can be used and manipulated in a healthy way by other classes or not, comes the levels of public and private visibility, which are the most used. The protected and packet visibility levels of java (and String of C ++) are intermediate cases for specific exceptional situations and in practice apply very rarely.

    In this way, with public or private access control it is possible to separate which part of the class corresponds to the behavior that is exposed to the external world of the part that is just some internal detail so that its implementation can function properly and perform what is proposed.

    Now comes the question: If you wrote the class X, then it does not make much sense for you to protect the class X code against misuse of itself, after all, it's the same code written by the same people . And it is because of this that programming languages in general have access control rules based on classes and not on instances. It does not make sense for a class's code to want to restrict access control to something even more restricted than just itself.

    In short, access control is something that is used to organize and protect code before it is submitted to the compiler, not objects in memory during execution. Instance is a concept that only comes up in another stage when the code is already running, and at this stage access control is no longer needed because the build step has already passed.

    In case this allows " one person to end up reading another person's mind", for this, the ideal would be to work with interfaces where a person sees other people and knows what they can do, but can not read your thoughts. Each person has their specific behaviors, which are often not known in depth by other people. Now when you work with class code, you already have all the details regarding the behavior and in this case if one person ends up reading the other's thinking improperly, it's because it's a programming error in the friend , and not from harmful interference by another class.

    Finally, there are some languages that end up implementing the restriction of access in term of instances. Scala has the Pessoa modifier. Ruby interprets private[this] that way.

        
    26.08.2016 / 17:47
    0

    Friend, in her example, from what I understand, what Maria is thinking is what Mary knows, her information, her attributes. If these attributes are private, for John to know what Mary is thinking, it is necessary to ask Mary. In case your example method ".fazQuestion ()" would be equivalent to a ".getPensing", ie if the fields / attributes of a class are private it is necessary to send a message / ask for the other object of the same class attribute. Therefore, it is not possible for such objects to "read the thoughts" of other objects.

        
    26.08.2016 / 14:57