Ok so I'm using this book: Core Java Volume I--Fundamentals.
It defines encapsulation as follows:
Encapsulation (sometimes called information hiding) is a key concept in working with objects. Formally, encapsulation is simply combining data and behavior in one package and hiding the implementation details from the users of the object.
From searching in SO, I know that that encapsulation and information hiding are separate concepts but used in conjunction. But, let's stick to the book's definition(which says encapsulation==implementation-hiding) for the sake of this question as this question uses the book's examples.
public class Math
{
. . .
public static final double PI = 3.14159265358979323846;
. . .
}
The book says this doesn't break encapsulation as its a constant. But doesn't the above code break the implementation hiding part of encapsulation(by the book's definition) since PI is visible to not only class but rest of program.
My question is actually a possible duplicate of this: Does a public static const variable break the encapsulation ideology? (tagged with C++ though) but the answer says that it does violate encapsulation(contradictory to the book) and that's ok. I understand if my question is closed because of this possible duplicate
Edit: I'll just post another example code as a comment mentioned PI isn't considered an implementation detail
public class System
{
. . .
public static final PrintStream out = . . .;
. . .
}
Great question. I don't think the examples you provided break encapsulation, at least not strictly.
The first example you gave is the constant PI and the second is an example that provides access to the out constant in System; presumably to make use of some code such as System.out.println("HelloWorld!");
. As others have already mentioned, PI
is effectively just a constant and users of the constant have no means by which to modify or influence the value. Users of PI
still need to reference the constant (which constitutes the API here) in their code. If PI
were modified (unlikely, but who knows) users would be safe from the implication of that change because they'd be required to recompile the code anyways.
A helpful way to think about encapsulation is to think about what would be required in order to violate encapsulation. Effective Java 3rd edition describes this well in Item 16, suggesting that without proper encapsulation "you can't change the representation without changing the API, you can't enforce invariants, and you can't take auxiliary action when a field is accessed."
A very clear violation of the above would be the following class (also in Item 16 of Effective Java):
class Point {
public double x;
public double y;
}
All fields are public and users of this API would be forced to use the fields directly. If later the author decided to add some validation checking before x
or y
could be accessed or modified then it would be impossible to do so without potentially breaking existing clients. The API would have to be significantly modified and likely breaking the behavior of users downstream.
Now let's look at the second example you provided:
public class System
{
. . .
public static final PrintStream out = . . .;
. . .
}
This seems very similar to the example of PI
above but there's a key difference: the field in question is a PrintStream. While the out
field itself is a clear part of this API that may now be hard to change (now that it's exposed clients are going to use and rely on it), the PrintStream
type is a class that is actually what's interesting here: users will be referencing methods on the class. Here we have the key functionality within the API of PrintStream
which can be evolved over time without breaking usage. It's also possible in the future to have the out
constant changed out to refer to a different PrintStream
subclass and users of the API should be unaffected.
Hope that helps.