26

The following is pseudo code, I tried it in Java and PHP and both worked:

class Test { 

    private int a = 5;

    public static function do_test(){
        var t = new Test();
        t.a = 1;
        print t.a // 1
    }

}

Test::do_test();

Why can you do this in OOP paradigm and what's the use of it?

9
  • 6
    Why wouldn't it be? In Java private members are not private to instance, but rather private to source file. The first use to come to mind is equals that has to check private fields of another instance. (Posting as comment, as this is short, and nothing about the OOP-ness of this approach)
    – Ordous
    Jul 2, 2014 at 10:15
  • 2
    Note that static methods don't have a this, so the only objects of their own class they can get at are the ones they create themselves (or that are passed in as a parameter). So if you consider this a violation of encapsulation or a security hole, it's not as if it's a very big one, and may not be worth plugging. Jul 2, 2014 at 10:21
  • 4
    Not sure why this got downvoted. The question might be trivial(ish), but the OP went through the trouble of testing the behavior in two languages before asking. That's way more effort than we usually see from newcomers.
    – yannis
    Jul 2, 2014 at 10:39
  • 1
    @YannisRizos Agreed, and in fact I don't think the question is trivial. It has implications for following the "principle of least privilege". It means helper functions that don't need access to an instance's internals should be defined in a separate class, and conversely when this convention is followed you'd know that whenever a static method exists within the same class, it's accessing internal state.
    – Doval
    Jul 2, 2014 at 11:45
  • 1
    In fact, when I asked my colegues all of them said this is impossible. That's why I didn't thought it's trivial
    – Ben
    Jul 2, 2014 at 12:42

3 Answers 3

19

In Java, private variables are visible to the whole class. They can be accessed from static methods and from other instances of the same class.

This is, for example, useful in factory methods. A factory method usually does initializations to an object which are so complex that you do not want to leave them to the application code. In order to do the initialization, the factory method often needs access to the class-internals you don't want to expose. Being able to access the private variables directly makes your life much easier.

However, when you would like to hide the implementation details of a class even from static methods or from other instances of that class, you could follow the private class data pattern. Put all private variables of a class into a private inner class and delegate any getters or setters to getters and setters of that inner class.

Another option is to define an interface for the class which declares all the public methods of the class and then only reference the class under that interface whereever possible. A reference to the interface-type can not be used to directly access anything not declared in the interface, no matter where (except with reflection, of course). When your use an object-oriented programming language which has no interfaces (like C++, for example), they can be simulated with an abstract base-class which is inherited by the actual class.

interface ITest {
     public int getA();
}

class Test implements ITest { 

    private int a = 5;

    public int getA() { return a; } // implementation of method declared in interface

    public static void main(){
        ITest t = new Test();
        t.a = 1; // syntax error: Interface ITest has no "a"
        System.out.println(t.getA()); // calls Test.getA, visible because ITest declares it
    }

}
2
  • Can you think of a situation when private class data pattern is useful? I personally use inner classes only in GUI like setups (Swing, etc) or static inner classes in coding exercises since I don't want an exercise to span multiple source files.
    – InformedA
    Jul 2, 2014 at 10:57
  • 1
    Hiding a class's internals from other instances takes away one of the advantages classes have over interfaces without getting anything back in exchange. A simpler and more flexible solution is to just use an interface.
    – Doval
    Jul 2, 2014 at 11:19
3

Some languages and runtime frameworks (e.g. Java, .NET) make the assumption that anyone who is compiling the code for a particular class can be trusted not to use any private members of any instance of that class in ways which would be detrimental to its correct operation. Other languages and frameworks are more restrictive in that regard, and do not allow access to private members of an instance except by code running on that instance. Both designs have advantages and disadvantages.

The biggest advantage of allowing any code within a class to access private members of any instance is that there are cases where that level of access is appropriate, and having private work that way eliminates the need to either have a different access qualifier available for that purpose or else force code to expose members more broadly than would otherwise be ideal.

An advantage of disallowing such access (as was the case in the Microsoft Common Object Model (COM)) is that it allows outside code to treat classes as interfaces. If a class ImmutableMatrix contains a private or protected double[][] backing field, and if code within the class examines the backing array of other instances, then it will not be possible to define a non-array-backed class (e.g. ZeroMatrix, IdentityMatrix) which outside code could use as an Immutable2dMatrix, without that class having to including the backing field. If nothing within Immutable2dMatrix uses private members of any instance other than this, then it would be possible to rename the class to ImmutableArrayBackedMatrix, and define a new abstract ImmutableMatrix class which could have ImmutableArrayBackedMatrix as well as the aforementioned non-array-backed classes as subtypes.

Note that such refactoring would not be prevented by having the language "allow" ImmutableMatrix to examine the backing array for instances other than this, unless the language took advantage of that ability and actually did examine outside instances. The primary effect of having a language restrict such usage is that it will make the compiler squawk immediately at any attempt to write code which would not be amenable to such refactoring.

2

Java is not strictly an object-oriented language, but a class based language - the class determines the operations and behaviour access rather than the instance.

So don't be overly surprised that it lets you do things which are not strictly object-oriented.

Since the method is in the same class-scope as the instance, it has full access to private members. Similar rules govern instances of inner classes accessing data from instances of outer classes - an instance of an inner class can access private members of the outer class.

This is inherited from C++, where it is useful for creating copy and move constructors. It also is useful for comparing or combining two objects where their value depends on members which are not publically accessible in an efficient manner ( for example, the getter for an array in Java should copy the array so that the client code cannot modify it, changing the internal state of the object, but having to copy arrays to compare object equality is not efficient )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.