0

As I've come to understand it, encapsulation (in Java) is the mechanism of wrapping related data and methods into objects in a way, that the data is hidden from other classes and only accessible through the methods of the current class (a.k.a. data hiding), correct me if I'm wrong.

While reading some tutorials, I see that they specify that the getter and setter methods should be public.

I get why it shouldn't be private but why not protected or default? Would the use of protected or default getter and setter methods still count as encapsulation?

JoSSte
  • 2,210
  • 5
  • 25
  • 40
piny88
  • 27
  • 3
  • Restricting the access makes it "more encapsulated", not less. Apart from that, though - getters and setters are to hide the implementation from "someone". Do you want to hide the implementation from the entire package or not? Do you want to hide the implementation from subclasses or not? It all depends on what you're trying to achieve. It might even be different for different attributes; e.g., if it's a simple value, why bother with the boilerplate getter? – user15187356 Mar 06 '21 at 22:03
  • related: [Encapsulation vs Information hiding](https://stackoverflow.com/q/13913174/1371329) – jaco0646 Mar 07 '21 at 01:44

4 Answers4

1

Encapsulation in Java is achieved by making a class's fields private. Weaker encapsulation is achieved by making them protected.

Getter and setter methods do not implement encapsulation. Rather, they provide a mechanism for certain kinds of interaction with encapsulated data. If the data were not encapsulated then getter and setter methods would not be required. As such, sure, you can provide protected or default-access getters and setters, and even private ones. Or none at all. It's all a question of what features you want your class to expose to whom.

When one makes getters and setters public it is because they provide features that are essential for use of the class, not because that level of access is a requirement for encapsulation.

John Bollinger
  • 121,924
  • 8
  • 64
  • 118
  • Perhaps you'll find the revised wording more satisfactory, @JanezKuhar. I can see how the previous might have been read differently than the new. – John Bollinger Mar 06 '21 at 23:18
  • You stated that "Weaker encapsulation is achieved by making them protected", does this also apply to default fields? – piny88 Mar 06 '21 at 23:37
  • @piny88, technically, I guess I would have to say "yes", since default access affords a strict subset of protected access. But I do consider it qualitatively different for a subclass to access members of its superclass than for other classes from the same package to do so. – John Bollinger Mar 07 '21 at 01:28
1

While reading some tutorials, I see that they specify that the getter and setter methods should be public.

That is often done in tutorials because it's easier to write, while also providing "some kind of object oriented feeling", because you still have some control using getters and setters.

You could (not recommended) also use public fields and omit the setters and getters completely:

public class Foo {
  public int i;
  public String s;
}

But when using setters instead you can for example validate the data:

public class Foo {
  public void set(int temperature) {
    if(temperature < 273) throw new IllegalArgumentException();
    this.temperature = temperature;
  }
}

But what if you need to validate multiple values at once? Using a setter you can only always validate the current value, but you can't validate multiple setter calls together. That's one scenario where public setters are bad.

The other thing is: Object oriented programming is much about telling names: setXYZ doesn't you tell much. For example setTemperature might be fine for a thermostat. But that's it. Maybe you even got something more advanced: setTemperatureLevel (values 1-5) which then sets the internal desiredTemperature and when this value is higher than the current temperature you want to set heater to true.

When using simple setters, you have no control if all those steps are done in the right order, or if maybe some step was skipped. But using a setLevel method that does all of that inside the class, there's no way to screw up for the method caller.

But of course there are places in the Java world where those public setters and getters are quite handy: In a lot of frameworks, like something for mapping database to DAOs, or DTOs for JSON de/serialization, it makes things easier. Because here it's used as a convention for reading and writing the fields of an object. Those objects are often referred to as JavaBeans.

But when it comes to your domain objects, I highly recommend to keep everything private you don't want others to access and/or manipulate.

Benjamin M
  • 20,265
  • 25
  • 105
  • 178
0

Accessors certainly can be protected. For example, an abstract base class might expose some internal state to subclasses by using a protected getter that isn't part of the API that consumers are supposed to use.

That said, getters and setters are normally used in the context of JavaBeans, where the getters and setters define the properties of the object. If they're not publicly visible, then while they do still provide encapsulation, they don't serve that particular purpose.

The tutorials you are reading are written from the perspective of the user (who is a developer) of some object. Such properties need to be public to do their job, and most property accessors are public.

chrylis -cautiouslyoptimistic-
  • 67,584
  • 19
  • 106
  • 140
0

Encapsulation is meant to prevent other objects from modifying the values directly.

If you make the getters and setters private, only other methods in that class will be able to call them. this may be becouse you want to validate the value, or because you want to ensure that there is support for multithreading, or some other issue.

If you make them protected, then inheiting and extending classes will be able to call them, nut no other classes, not even your main method would be able to call the getter and setter.

If you want to expose the values only, nothing prevents you from having a protected/private setter, and a public getter, or no setter at all ( you would have to instantiate the value in another method, or in the constructor )

JoSSte
  • 2,210
  • 5
  • 25
  • 40