108
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?

Arvindh Mani
  • 130
  • 3
  • 12
Nageswaran
  • 7,481
  • 14
  • 55
  • 74
  • 7
    I believe the OP considers the "Person" object passed to "someMethod" to be a separate object, and therefore the method shouldn't have access to it's private members... even though it's within the "Person" class. – Inisheer Jun 10 '13 at 15:29
  • 1
    Some languages don't do this (Newspeak for example). You're not likely to get a good answer as to why. You will get answers working backwards from what happens to be specified. – Tom Hawtin - tackline Jun 10 '13 at 16:33
  • The `someMethod` is not valid. It does not return anything. It must be `void`. – Nicolas Barbulesco Aug 21 '13 at 09:33
  • 1
    If this was not the case, it would be very hard to write copy constructor and assignment operator imo. – rozina Mar 11 '14 at 07:05
  • In Scala you can specify `private[this]`. That's a Scala feature I'm guessing Java will never add. However, I only came upon this question because I had an IDE glitch telling me that instance A couldn't access instance B's class private fields even though they're the same class. I saved and the light went from red to green without passing through yellow. – Alonso del Arte Sep 21 '21 at 18:59

9 Answers9

81

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?

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.

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

Community
  • 1
  • 1
Iwan Satria
  • 1,903
  • 1
  • 19
  • 22
  • 6
    This is probably the reason. But this is **a bad idea**. This encourages bad practice. A developer accessing a field of `Person`, in the class `Person`, does not have to know the implementation of the whole class. The good practice is to use the accessor, without having to know what operations the accessor does. – Nicolas Barbulesco Aug 21 '13 at 09:37
  • 19
    @NicolasBarbulesco I think the reason given in the answer is sound. Say for example you want to implement the `equals(Object)` method in a Java class to check equality of a `Person` object with another instance of `Person`. You may want to enable the outside world to check if the two instances are equal, but you may not want to expose all of the class's private fields necessary for checking equality to the outside world using public accessor methods. Having class-level access to `private` fields enables implementing such a method without the induced necessity to implement such public methods. – Malte Skoruppa Nov 04 '15 at 23:21
  • 1
    @MalteSkoruppa - This is a good example (implementing the method `equals`). – Nicolas Barbulesco Nov 20 '15 at 10:15
  • @MalteSkoruppa - However, implementing the method `equals` could be done by calling private accessors. – Nicolas Barbulesco Nov 20 '15 at 10:19
  • @NicolasBarbulesco Yes of course, but the point is, whether you use private accessors or directly access private fields for implementing the method, `private` has to grant class-level access. I agree that using accessors is generally a good habit, though in this case it is mostly a matter of context and personal style. Note that both Joshua Bloch in *Effective Java* (item 8) and Tal Cohen in [this Dr. Dobbs article](http://www.drdobbs.com/jvm/java-qa-how-do-i-correctly-implement-th/184405053) directly access private fields in their code listings when discussing how to implement `equals`. – Malte Skoruppa Nov 24 '15 at 09:12
27

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.

Wei Qiu
  • 886
  • 9
  • 16
  • 2
    This answer needs to be voted up! Other answers just re-state the 'rule' but only this one really unveals the reason behind the rule and hits the point. – mzoz Mar 16 '18 at 06:59
  • 5
    But wouldn't it be better to have an object be responsible for providing copies of itself? Then, if you need a deep copy of an object, it doesn't matter if you're another object of the same class or an object of a different class: it's the same mechanism, `o.deepCopy()` or whatever. – dirtside Oct 08 '19 at 20:46
17

See the Java Language Specification, Section 6.6.1. Determining Accessibility

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.

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.

jlordo
  • 37,490
  • 6
  • 58
  • 83
  • 1
    The OP's question is not specific to Java, but about the philosophy of this design choice by many OOP languages. This answer just re-states the facts, without explaining why the decision made this way. – wlnirvana Jan 20 '21 at 10:28
6

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:

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.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • This is something similar to dependency injection. In which you can also inject some other class's object, where you can't access the private variable. – Nageswaran Jun 10 '13 at 15:24
  • Sure, if you are trying to construct a class A from an object of class B, and B has private component, then either A needs to be declared a friend, or can only see public parts [possibly protected, if A is derived from B]. – Mats Petersson Jun 10 '13 at 15:27
  • In java and .net there is no concept of friend. In such cases, how to handle this? – Nageswaran Jun 10 '13 at 15:30
1

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

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.

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.

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}.

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.

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.

Temp Agilist
  • 233
  • 1
  • 2
  • 8
0

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

darijan
  • 9,725
  • 25
  • 38
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.

ola
  • 882
  • 2
  • 12
  • 29
-1

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.

Sachin Jadhav
  • 111
  • 2
  • 6
-2

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

Modificando metodos y campos privados con Refleccion en Java

lennon310
  • 12,503
  • 11
  • 43
  • 61