Java protected fields vs public getters

Java

Java Problem Overview


What is better practise and why: accessing base class variables through a protected field or a public getter on the private field.

(The getter will be public regardless)

Java Solutions


Solution 1 - Java

If there's going to be a public getter anyway, why would you want to expose the field itself more widely than absolutely necessary? That means it's immediately writable by subclasses (unless it's final to start with).

Personally I like all my fields to be private: it provides a cleaner separation between API and implementation. I regard the relationship between a superclass and a subclass as similar to that of a caller and callee - changes to the underlying implementation shouldn't break subclasses any more than they should break callers. The name of a field is an implementation detail which shouldn't impact other classes.

Admittedly my view is occasionally seen as somewhat extreme...

Solution 2 - Java

You should always program against the public API of a class, that is, use the public methods.

The reason is simple. Someday in the future, you or someone else might want to change the implementation. This should always be possible. If you rely on instance variable, you limit yourself.

Also, when accessing the variable, you can not control if that variable is read-only nor can you add checks when this variable is changed.

If you use setters/getters, you can allways add validation, checking etc later on. You can also only provide a getter to make a variable read only.

Solution 3 - Java

Direct field access is not preferred. Use public or protected setters and getters.

The getter need not be public - if you wan to hide the data from "outsiders", but give the data to subclasses, use protected

Solution 4 - Java

Some of Sun's recommendations on controlling access to fields are here. Note that making a field protected exposes it to the package as well, not only to subclasses. Generally, as stated at the link above, fields should be private unless there is a very good reason not to do so.

Solution 5 - Java

Effective Java 2nd Edition says

> Item 13: Minimize the accessibility of classes and members > > The rule of thumb is simple: make each class or member as inaccessible as possible. In other words, use the lowest possible access level consistent with the proper functioning of the software that you are writing.

So if you are not sure why you need a protected class member (ie you don't need the field to be accessible to subclasses or classes in the same package), then declare it private. If you wish to set it from outside the class, then make a public setter.

However, if your member is final, then making it protected might be ok in some cases (ie it doesn't reveal sensitive information).

One potential security issue I would like to mention is that if you have an array declared protected final (even public final), the array reference is final (cannot be modified), but the objects held in the array are not final (an intruder could change the array contents).


If you know c++, you probably know that

const int * someMember

is different from

int * const someMember

The latter is like the final array in java.


The fix for the aforementioned security hole is to return a deep copy of the array or return it as a read only list.

Solution 6 - Java

Generally, you should use Sun's recommendations. There is one big exception: if you're programming for Android.

The reason is performance. With every virtual method invocation, there is overhead involved in using the lookup table to route the method to its object. This overhead is not involved when accessing a local variable.

Here are some links that explain this in a little more depth:

http://developer.android.com/training/articles/perf-tips.html#GettersSetters

http://blog.leocad.io/why-you-shouldnt-use-getters-and-setters-on-android/

It's important to know what you're trying to accomplish:

  1. The field's value should be accessible to client code, using a public interface.
  2. The field is meant to be used by subclasses.

In plain ol' Java, getters and setters accomplish both tasks. But Android is different. If you're doing #1, then you should use public getters and setters. If you're doing #2, then you should use protected fields. If you're doing both, use both.

Solution 7 - Java

I would like to present you with some arguments protecting "protected" fields in Java: "You may favor accessing base class members using protected fields over public accessors in situation where you need to avoid value validation". However if this is not the case, then private fields with public accessors should be used, to compliment hermetization.

The principle of getters and setters is to provide validation to the values inputted and outputted to the class member. However, in OOP languages, we operate on objects not classes. Base class and specialized class represent a single object, that is why it is perfectly fine to access specific class members over protected field.

Consider the following abstract example with a car:

  • you have a base class Car and the derived class Porshe.
  • Car class may have field like engine, which value is not set in Cars constructor (maybe the type of engine is known only after object initialization)
  • You create a Porshe class object that contains some logic used to calculate engine type using some external data.

In this example, it is expected that engine field has a public getter, so car users know what engine the car has. However, there is no public setter as we expect car drivers not to temper with the engine! That is why, it is perfectly fine to make engine a protected field, so the Porshe class can set its value at some time in future.

Yes, some people will probably say "then use protected setter!". And I will repeat: in OOP languages we work with objects not classes. Single responsibility principle - yes, but as object not as class. If you say: "at some point if we use protected fields over 3 or 5 inheritance levels, it may be troublesome to understand what happens to the field if each class performs some operation with it". And then I answer: That is another antipattern - your object is probably too big at this point and voids Single Responsibility principle.

Solution 8 - Java

Accessing protected fields from a subclass is one of the ways that inheritance violates encapsulation. Using the public API is better for this reason.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDD.View Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - JavaphischView Answer on Stackoverflow
Solution 3 - JavaBozhoView Answer on Stackoverflow
Solution 4 - JavaFeanorView Answer on Stackoverflow
Solution 5 - JavaAdrianView Answer on Stackoverflow
Solution 6 - JavaKarl GiesingView Answer on Stackoverflow
Solution 7 - JavaAndrey BorisovichView Answer on Stackoverflow
Solution 8 - JavaDanielView Answer on Stackoverflow