Why can objects other than the same class access private fields from each other?

Asked

Viewed 635 times

8

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

In object-oriented modeling we have the concept of encapsulation (hide implementation) that has no direct relation to protection, but observing one of the purposes of the POO which is to provide a closer modeling of 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 "improper" 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!

The Java language offers some protection feature in this regard? In Java do we have the feature of isolating parts of memory for security reasons? (This question is only for reflection or extra comment)

Clarifications

  1. The example shows situations where joão (instance) accesses attributes/fields of Mary that should be particular only to her.
  2. The word "private" is more in another context than access modifiers in Java, here I put this word as if it were "something particular" that only the instance should have direct access to (think of other attributes also as an attribute that holds someone’s "password", etc.).

So I asked the question if in Java we have the feature of isolating parts of memory for security reasons.

  • I don’t understand the connection between your reasoning and the informed code. If thoughts are public, it will be accessible even if it is private, this call will give error.

  • @diegofm the code was just a joke, think of the question: Why instances of one class can access private fields from each other?

  • They cannot, private field is accessible only by that instance. There is no sharing of private methods, nor if there is inheritance between classes.

  • http://stackoverflow.com/questions/30604431/why-can-an-instance-of-a-class-access-private-fields-of-another-instance-of-its

  • @diegofm, you cannot? =)

  • I still haven’t connected the rationale of the question to the code. There the code shows a class accessing its own private member, its code is doing something completely different. If thoughts are private, the way you’re doing in this code, you won’t even compile.

  • read more calmly the @diegofm example, see "foo.secret = 100;" it used "foo" which is another instance of Foo.

  • Yes, not here. But hope that someone who might understand can answer you. I really didn’t understand code with doubt.

  • I think the confusion is that you only spoke of John, but at no time do you use him, except in the comments.

  • 1

    I think I’ve seen this problem of John and Mary mixing thoughts on the site, but I can’t remember where it was. I’ll do a search, and if you find the link to the post I paste here.

  • @Randrade, I thought the comments were enough. The mistake was mine, I should have made it clear that John was the one who was accessing Mary. I thought because I only had 2 objects there would be no need, but that’s okay! Living and learning! Thanks for the comments!

  • 1

    No problem. I only spoke because the clearer your question, the greater the chance to get good quality answers.

  • 1

    @guiwp I took the liberty of making your title a little clearer. As it stood, I was inducing the error of understanding that occurred here.

  • @Pabloalmeida, thank you very much

  • 1

    guiwp, I think you could change your example to become more didactic. If your example included a method void leMente(Pessoa outraPessoa) { System.out.println(outraPessoa.pensamentos); } and a call joao.leMente(maria); there would be no room left for confusion.

  • @Anthonyaccioly vc gave a good suggestion, feel free to modify! =)

  • 1

    guiwp, done. Take a look to see if you agree with the editions.

Show 12 more comments

4 answers

11


The question example 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 that. C++ did so, C# also.

Justification

One justification for opting for this is that the compiler is analyzing code that is not running. He doesn’t look for objects, he just looks at what’s in the class. It cannot guarantee that the object that is there is an object different from the current one. It can be the current one.

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

A good example

How would a equals() between two objects of the same class, one of them is the parameter this implicit and other could be an explicit parameter 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
}

I put in the Github for future reference.

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

Encapsulation

I don’t like that definition given in the question. For me, from what I understood in everything I studied, encapsulation is putting everything in a single capsule, everything that refers to that as one thing. This ends up creating an abstraction, but hiding the implementation detail itself is something else. So I’m going to talk more about abstraction than encapsulation here, although they are well related (I could talk about information Hiding).

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

It is used for encapsulation, which refers to the class and not the object. Any object in this class is "reliable" from a code point of view.

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

Completion

Then understand that is not to protect access to object, is to ensure internal visibility in the 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.

  • Mr @bigown, thanks comment. 1) The question example does not show what was asked. A: It was only to show john (an instance) accessing fields of another instance (mary). The part commented with "john" was John accessing, I hope to have become clearer now.

  • I brought the word "private" to another context, I don’t know if you noticed. But maybe I can make the text clearer next time! Alias you do not read my thoughts rsrs

  • 3

    I think this confusion comes especially from the misunderstanding that access modifiers have some relationship with data security. That’s not their intention. The idea is to prevent client codes in your class from relying on internal implementation details to the point where you can’t change them in the future. If the code that is trying to access the attribute is its own code (regardless of who is currently running it), then it is all under your control.

  • 1

    @Pablo your comment reinforces what is encapsulation, very good! I’m learning a lot. thanks

  • 1

    +1 as a gesture of humility in realizing that I have much to learn =)

  • 3

    That’s why scala scopes may include qualifiers. private[this] does exactly what you want.

  • perfect @Anthonyaccioly, I think q won’t take long I’ll have q learn scala!

Show 2 more comments

8

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

The private member of a class aims at code encapsulation. This serves both to maintain the organization and to prevent agents outsiders the class unexpectedly modifies it.

As in the example (copied to the code snippet below for ease) the class handles an instance of itself. This does not break the encapsulation rule that makes it 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 tries to change private member of Foo an error would be triggered.

Like Foo changes an instance of Foo (an instance of the same class) internally Java (as other languages also do) understands as a normal behavior.

6

Because the purpose of access control levels is not that.

The idea of encapsulation is to ensure that its classes cannot suffer harmful interference from other classes.

That is, if you designed the X class to solve the Y problem, you don’t want your neighbor to design a Z class that uses its X class in a totally inappropriate way and end up breaking the premises that underlie its proper functioning. With this access control, it is much easier to develop robust, safe, well tested and more idiot-proof code, thanks to encapsulation.

The idea is you expose the other classes, which may have been designed by different people, only the valid ways that make sense to interact with them. To take a concrete example quite beaten, imagine the class String. She’s got a private camp like char[] (in Openjdk 8), and so that a String can be used safely and that makes sense, you do not want the class Gambiarra123 that your neighbor’s nephew invented end up messing with the Strings of the whole 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 package visibility levels of java (and the friend of C++) are intermediate cases for specific exceptional situations which in practice apply very rarely.

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

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

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

In case it allows "one person ends 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 cannot read their 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 behavior and in this case, if one person ends up reading the other person’s thinking improperly, it’s because it’s a programming error in the class Pessoa, and not harmful interference by another class.

Finally, there are some languages that end up implementing the access restriction in terms of instances. Scala has the modifier private[this]. And Ruby plays the private thus.

And yet, from Java 9, there is also the concept of encapsulation at the module level, not just of classes. The logic is the same. Within the same module, you can access things inside that module because it’s the same code that should or should have been designed cohesively by the same people. However, access to the internal details of a module is blocked from other modules to prevent improper access to internal parts of the module from compromising its operation.

  • Since he said that "programming languages in general", this here is only an addendum, a curiosity. Ruby is an example of language that the private applies an instance-based access control.

  • @Gabrielkatakura It’s because Ruby doesn’t have a well defined and separate compilation step from the execution, and so the access control is pushed to the runtime.

  • "It makes no sense for a class code to want to restrict access control to something even more restricted than just itself." Have you ever imagined behaviors that can only be predicted at execution time? imagine that I have an AI algorithm that gives freedom of objects (People) inspect each other within a virtual world in order to gain advantage, it would be interesting to restrict access to certain members in certain situations

  • 1

    @guiwp For this, the ideal would be to work with interfaces, where a person sees other people and knows what they can do, but cannot read their 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 behavior and in this case, if one person ends up reading the other person’s thinking improperly, it’s because it’s a programming error in the class Pessoa, and not harmful interference by another class.

  • I think it’s worth revisiting here and putting things from Java 9 modules. What do you think, @Victorstafusa?

  • 1

    @Jeffersonquesado Feito. Although to be honest, this is a little outside the scope of the question, although it is still a relevant supplementary information.

Show 1 more comment

0

Friend, in your example, as I understand it, what Mary is thinking is what Mary knows, her information, her attributes. If such attributes are private, for John to know what Mary is thinking it is necessary rather to ask Mary. In this case his example method ". fazPergunta()" would be equivalent to a ". getPensamento" that is, if the fields/attributes of a class are private it is necessary to send a message/ask to the other object of the same class about a given attribute. Therefore, it is not possible for such objects to "read the thoughts" of other objects.

  • thank you Elipe, but that’s just the problem! In Java language an object of the Person class freely accesses the thoughts of another person! I have not yet known how to make a member of one class truly particular to other instances of that same class.

  • test yourself; create the classes and modify each other’s "thinking" member

Browser other questions tagged

You are not signed in. Login or sign up in order to post.