Everyone knows that Java supports data hiding.
I went for an interview. Then interviewer asked me that if Java supports data hiding by using private as datatype.
He said if we use setters and getters in that class then by using those setters and getters we can get that private data easily.
So how this is supporting data hiding here?
It may be possible that he was trying me catch me in trap. But I could not reply this.
What should I reply for this?
He was arguing that if "Data Hiding" is an OOP principle then aren't we breaking it by exposing via getters and setters. I think he wanted you to spell out the difference in principle between being able to access a data member directly vs. doing it via a getter or setter. In the former case a client of the class can mishandle the data, assign it a value that the class designer has not designed the class to handle (for example set the age of a student as 500).
In the latter (using a setter) the class designer has imposed certain restrictions on what values can be assigned to the data. In the age example the setter might be something like:
void setAge(int age) {
if(age<3 || age>100)
return;
this.age=age;
}
assuming that students of age below 3 and over 100 aren't allowed. So you are still hiding your data but allowing means to manipulate it in a way consistent with the logic of your module.
Very simple Example:
Version 1 of class could have getter like this.
public int getTotal() {
return total_;
}
Version 2 could do this
public int getTotal() {
return a + b;
}
We've changed how the class is implemented, but clients of the class don't need to change as well, because the data is hidden behind a getter.
Data hiding is bad term, better say data encapsulation. In java access to private members is done through accessors and mutators ( getter and setter), it is all about hiding and controlling access to your members so you can control how inner state of instance will be modified.
I think if you mention something about java reflection / metadata -> you will get bonus points
The class fields are hidden, if we declare them private. No doubt (we ignore nasty reflection tricks). If we want to make the values accessible, we provide access methods (getter/setter for example).
But there is no requirement to provide getters and setters for all fields or to name them according to fields (in general).
The class internals (the fields) are perfectly hidden.
protected String name;
public void setName(String newName){
if(newName.length() > 5) this.name = newName
}
public String getName(){
return this.name;
}
In this simple case the name attribute can be accessed by its name in this class and in all its children. If you want to set the value of name from an unrelated class than you will have to use the setName() method where you can apply some validation for example.
Here you can find any information you need about this special methods.
Be aware that any property of a class can be accessed if the mutators and accessors are public. This is one of the key points of the Java Bean concept and almost all java frameworks relate to this concept at one point or another.
What you are talking about seems to be Encapsulation. Basically the getters and setters allow you to expose class variables as you like and hide any others. Getters and Setters also allow you to perform any other necessary steps such as validation.
Getters and Setters can have different access modifiers themselves, so you can expose data to certain classes but not others by using different access modifiers.
I bet he was waiting that you will refer to "immutable" types also.
PD. private is no type, it is an access modifier.
The support for "data hiding" can be explained by the fact that the getter and setter methods are like gateways to the data.
It is only by convention - the JavaBeans convention to be exact - that it is expected from them to operate on the member they are named after. They could do anything else and it would still be perfectly compilable and legal java.
Maybe, he mean Encapsulation as information hiding.
If you make the setter & getter public/protected/default, then you could access the private members on different levels .. if you make setter&getter private then the data is really hidden. This last way to go makes no sense at all though
You may think about implement set/get methods in many different ways.
As some answers already pointed out, set/get don't have to actually set or return actual members.
For example, let's say you have a Coordinate class with set/get for (x, y). The inner implementation might be based on polar coordinates:
private double radius;
private double angle;
and the get/set for (x, y) do some coordinate transformation with sin and cos.
You could change the implementation of the class to any other system of coordinate at will and still just keep the set/get for (x, y) as public methods.
So, to sum up, my answer to the question would be: the public interface of a class might provide set/get, but the actual implementation can (and should) be hidden by making all members private (or protected). So we could say that having public set/get on private data is "implementation hiding" rather than data hiding.
Data Hiding and Encapsulation are frequently mistaken for security by first time oops learners. Its important to understand that data hiding and encapsulation have nothing to do with security.
These concepts exist to ensure that inheritance of a class A, from class B (class B extends A) does not inherit the "encapsulated" members.
I hope this kinda clarifies your confusion, and also motivates you to read and study more. Your question is very basic to the OOPS concepts. And the interviewer is not trying to corner, you but ask you very basic questions on OOPS. Study hard!!!
Related
This question already has answers here:
Why are getter and setter method important in java? [duplicate]
(6 answers)
Closed 7 years ago.
Encapsulation is hiding the data. I would like to hear some really interesting answers here.
What is the point behind keeping variables as private when we already declare public setter methods for variables?
I understand the usage of encapsulation but when we are making the setters as public what is the point behind keeping the variables as private, we can directly use public access modifiers.
Is it because we do not want others to know the exact way we are storing data or managing data on the back-end?
Is it because we do not want others to know the exact way we are
storing data or managing data on the back-end?
Yes, that's the point. It is related to the concepts of abstraction and information hiding too.
You provide a public setter that when invoked by the class client will have the effect that you have documented. It is none of the client's business how this effect is actually achieved. Are you modifying one of the class attributes? Ok, let the client know that, but not the fact that you are actually modifying a variable. In the future, you could want to modify your class so that instead of a simple backup variable it uses something completely different (a dictionary of attributes? An external service? Whatever!) and the client will not break.
So your setter is an abstraction that you provide to the client for "modify this class attribute". At the same time you are hiding the fact that you are using an internal variable because the client doesn't need to know that fact.
(Note: here I'm using the word "attribute" as a generic concept, not related to any concrete programming language)
I fully agree with Konamiman's answer, but I'd like to add one thing:
There are cases where you really don't want that abstraction. And that's fine.
A simple example I like to use here is a class for a 3-dimensional float vector:
class Vector3f {
public:
float x;
float y;
float z;
};
Could you make those fields private and provide setters instead? Sure, you could. But here you might argue that the class is really just supposed to provide a tuple of floats and you don't want any additional functionality. Thus adding setters would only complicate the class and you'd rather leave the fields public.
Now, you can easily construct scenarios where that might bite you later on. For instance, you might one day get a requirement that Vector3fs are not allowed to store NaNs and should throw an exception if anyone tries to do so. But such a hypothetical future problem should not be enough to justify introducing additional abstractions.
It's your call as a programmer to decide which abstractions make sense for the problem at hand and which ones would only get in your way of getting the job done. Unnecessary abstractions are over-engineering and will hurt your productivity just as much as not abstracting enough.
Bottom line: Don't blindly use setters everywhere just because someone claimed that's good practice. Instead, think about the problem at hand and consider the tradeoffs.
Because by encapsulation we provide single point of access. Suppose you define a variable and its setter as follows
String username;
public void setUsername(String username){
this.username = username;
}
Later you like to add some validation before setting username property. If you are setting the username at 10 places by directly accessing the property then you don't have single point of access and you need to make this change at 10 places. But if you have one setter method then by making a change at one place you can easily achieve the result.
Think about this : I'm representing a real life object, a Lion through a class. I'd do something like this.
class Lion {
public int legs;
}
Now my class is needed by some other developer to create an object and set its legs field. He'd do something like this
Lion jungleKing = new Lion();
jungleKing.legs = 15;
Now the question is, Java won't restrict him to setting any number more than 4 as the number of legs for that object. It's not an error, and it'll run just fine. But it's a logical blunder, and the compiler won't help you there. This way a Lion may have any number of legs.
But if we write the code this way
class Lion {
private int legs;
public void setLegs(int legs){
if(legs > 4){
this.legs = 4;
}
else this.legs = legs;
}
}
Now you won't have any Lion with more than 4 legs because the policy of updating the fields of the class has been defined by the class itself and there's no way anyone not knowing the policy is going to update the legs field because the only way to update the legs field is through the setLegs() method and that method knows the policy of the class.
Although Konamiman's answer is spot on, I'd like to add that, in the particular case of public setters versus directly exposing public fields you are asking, there is another very important distinction to keep in mind apart from information hiding and decoupling implementation from the public surface, or API, of a class; validation.
In a public field scenario, there is no way to validate the field's value when it's modified. In case of a public setter (be it a Foo {get; set;} property or a SetFoo(Foo value)) method you have the possibility to add validation code and launch required side-effects and this way ensure that your class is always in a valid or predictable state.
What if you do want to a range check before assignment? That's one of the cases I use setters and getters
More or less simple and realistic example I encountered in practice is an Options class, which has a lot of setters and getters. At some point you might want to add new option which depends on others or has side effects. Or even replace group of options with Enum. In this case setA function will not just modify a field, but will hide some additional configuration logic. Similarly getA will not just return value of a, but something like config == cStuffSupportingA.
Wikipedia has a good overview of [mutator methods(https://en.wikipedia.org/wiki/Mutator_method), which is what setter methods are and how they work in different languages.
The short version: if you want to introduce validation or other logic that gets executed on object modification it is nice to have a setter to put that logic in. Also you may want to hide how you store things. So, those are reasons for having getters/setters. Similarly, for getters, you might have logic that provides default values or values that are dependent on e.g. configuration for things like Locale, character encoding, etc. There are lots of valid reasons to want to have logic other than getting or setting the instance variable.
Obviously, if you have getters and setteres, you don't want people bypassing them by manipulating the object state directly, which is why you should keep instance variables private.
Other things to consider include whether you actually want your objects to be mutable at all (if not, make fields final), whether you want to make modifying the object state threadsafe with e.g. locks, synchronized, etc.
Setting fields as private documents a powerful fact: these private fields are only directly used within the current class. This helps maintainers by not having to track down field usage. They can reason better on the code by looking at the class and determining that the effects on and from these fields with the class' environment go through public and protected method calls. It limits the exposure surface on the class.
In turn, defining a "setter" for a private field is not about giving it publicity again. It is about declaring another powerful fact: an object belonging to this class has a property that can be modified from the outside. (The terms object and property are used in the sense of a bounded part of the whole and an observable fact about this part, not in the OOP sense)
Why then declare a "setter" on a field when making the field public would suffice? Because declaring a field not only binds a name to a property of the objects of the class, but also commits to use memory storage for this property.
Therefore, if you declare a "private field with a setter", you declare three things:
You declare that the name you gave to the field/setter cluster represents a property of the object which is of interest when the object is seen as a black box.
You declare that the value of this property is modifiable by the environment of the object.
You declare that in this particular concrete class, the property of the object is realized by committing some memory storage to it.
I advocate that you never make your fields private with getters and setters indiscriminately. Fields are for describing storage. Methods are for interactions with the environment. (And the particular case of "getters" and "setters" are for describing properties of interest)
I am learning get and set methods, I was just wondering if these can only be public, and do they need to be written for every instance variable in a class?
No.
Many internal variables should never be edited, such as states of computations.
If a field is private and has no getter/setter, it is that way for a reason and is acceptable as long as you don't need to access it outside the class.
If it is public, there's no point, and if protected, it's per-package or subclasses not necessarily in the same package.
Without a modifier, it's package-private.
If you want to make a field private and the getter/setter controlled you can use access levels as well.
On that note, if you want, you can perform validation inside a setter to ensure only acceptable values are set. Then, you can either silently reject, return false if the setter is a boolean, or throw an exception in severe circumstances.
I am assuming you are talking about encapsulation.
The whole point of these methods is for them to be public so that they can pass the value of your variable somewhere else in the application.
For achieving this with many variables, you may consider using 'listeners' (Observer Pattern Theory) which are basically custom interfaces that work with a custom class that contains many of these get and set methods.
More on encapsulation:
http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)
More on Observer Pattern Theory
http://www.youtube.com/watch?v=UEtyGP994X0
You need to have public getters and setters for your object to function as a JavaBean.
If you don't have a JavaBean requirement for your objects, then you don't need/have to provide public getters ( and especially setters ) in your classes.
Get and set methods in Java are just normal methods. They don't have to be public, but they wouldn't be very useful if they weren't public.
They don't need to be written for every instance variable in a class. If there are instance variables whose values depend on other values, then it may not make sense for them to have setters, e.g. a totalPrice instance variable that depends on a quantity instance variable.
If you want instance variables that shouldn't change, i.e they are immutable, then don't provide any set methods at all.
These methods provide your interface to the caller. They provide the operations on your object that you allow, so that the caller can't set your values to an invalid state, e.g. a count of -1 or a latitude of 91 degrees. This is "encapsulation", or hiding your object's implementation from your caller.
There is no java rule for making getters and setters public but these are made public for a reason.The point of getters and setters is that only they are meant to be used to access the private varialble, which they are getting or setting. This way you provide encapsulation and it will be much easier to refactor or modify your code later.Using getter and setter functions allow for constraints and encapsulation. Lets say x is the radius. shape.x = -10 would not make much sense. Also, if someone tries to set an illegal value, you can print an error, set a default value, or do nothing. It is good practice to make member variables private so they cannot be modified directly by programs using them.
A good article on the usage of getters and setters:
http://java.dzone.com/articles/getter-setter-use-or-not-use-0
Basically Yes, and No.
Yes, Get and Set methods (also called "getters" and "setters" or accessor methods) should almost always be public (although they can be otherwise -- there's a difference between can and should). The point of getters and setters is usually so other classes can access the encapsulated instance variables.
Exeptions:
You might make an accessor method to be protected if you only want child
classes or other classes in the same package to have access to those
methods.
You might use a private (or protected) setter if you want to
use special logic to set a variable (like concatenating it)
and you don't want other classes to be able to set the
variable.
No, they shouldn't always have accessors. Sometimes a variable should only have a getter (for instance, if that variable is final), and sometimes a variable shouldn't be accessed at all, and therefore you would not give it any accessor methods.
Get and set methods were designed originally for JavaBeans, classes stylized so IDEs and application programs can detect what properties the classes have and what event listeners they support. Through a limited version of reflection called introspection, tools can analyze the classes, and even if the programmer did not want to use is/get/set methods he could write BeanInfo classes that tell what methods be used instead.
Look at the Javadoc for java.beans.Introspector. and java.beans.BeanInfo. This provides ways to document additional information, including methods exposed to other tools and metadata about properties. For example, a TemperatureGauge class could expose the minimum and maximum temperature so a Swing program can set the limits of a slider without the programmer looking the information up.
Still, one should not expose more than one has to expose. You may need to limit access to getters and setters. You may need them for database tools, but you may not want ordinary programming to touch properties. This leads to ideas like OSGI or proxies where methods are limited to specific packages.
For example, one common tactic is to have getters only, to mark variables final, and build objects in the constructor. For example,
public final class Complex {
private final double re;
private final double im;
public Complex(double re, double I'm) {
this.re = re;
this.im = im;
}
public double getReal() {
return re;
}
// more getters, arithmetic, etc.
}
Note that I named the method slightly differently than the variable; that's okay.
On the other hand, there is a style of programming where one eschews getters and writes methods that tell the object what to do. Consider a Name class with givenName and surname instance variables. Then, add this method:
public void writeFormally(Appendable app) {
app.append(surname)
.append(", ")
.append(givenName);
}
You see this sometimes in Model-View-Presenter systems, like GWT and its HasText interface.
Unless you are writing code that deals with dependency injection systems or that use reflection to have your objects communicate with database, don't worry about the specifics of getters and setters. Just do what comes naturally and limit your objects' exposures. Also, every time you are tempted to write:
x.getA().getB().getC().setZ(42);
Rewrite the code to get rid of the chain of gets and sets. Look up the Law of Demeter in The Pragmatic Programmer.
Use protected if you want only child classes to access the field. However, if you want other classes to access the field, public is the way to go. Your decision should be based on the scope of access.
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?
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.
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.
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.
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.
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.
Because the private access modifier renders it visible only within the class. This method is still IN the class.
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.
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.
With reflection concept in Java is possible modify fields and methods privates
Modificando metodos y campos privados con Refleccion en Java
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Are Getters and Setters evil?
I can't find a logical reason behind having a private variable with a getter and a setter that does nothing but directly handling the value being preferable to having a public variable.
Am I missing something?
Because,
Validation is one reason. Keeping the field name out of the public API also allows you to change it later without breaking the API. And it allows you to change the class later in other ways as well, e.g. moving the field to some other class (so that the public setter would call a setter in a different class). Having the setter called also allows you to do other things, e.g. notify interested other components of the change of value. None of this would be possible if the field was accessed directly.
They are preferred to future proof the code. In the future if you want to eliminate the variable or use another variable to derive this variables value - the change is simpler. You just need to change the getter/setter, the rest of the code remains unaffected. This is not the case with direct access to the variable.
As #user370305 already mentioned one reason is validation.
Other reason is types conversion. Setter may accept string and parse it to integer.
Yet another reason is data encapsulation. It is not necessarily to have a simple filed stored in the same class. Method setName(String) of class Person may store the name in more complicated data structure. Using simple field does not allow you to change the internal implementation of class Person without affecting code that uses it.
EDIT:
yet another technical reason.
It is much easier to discover and debug code with getters and setters. If some field is changed unexpectedly you can just toggle break point into appropriate setter and find the problem very quickly. If this field is public and you have 1000 references to this field you theoretically have to put 1000 breakpoints in all these places.
1. Encapsulation has different use in different context, In design patterns its like behaviors that keeps changing needs to be encapsulated in abstract class, or interface.
2. Having private instance variable and public getter setter is b
3. Its mainly done to Validate the input from the user... Setting the value to an instance variable directly is dangerous.
Eg:
int dogAge;
System.out.println("My dogs age is :"+dogAge);
Now what if someone gives a negative age... then.......???
So we must do it this way...
int dogAge;
public void setAge(int age){
if (age>0){
dogAge = age;
}
else{
System.out.println("Not a valid age");
}
}
public int getAge(){
return dogAge;
}
System.out.println("My dog age is :"+ getAge());
Its simple .. if you make those variable public then you give rights for ading any values to them .
But if you do that via getter or setter ... you can put checks over it and control the input or conversion without letting the end user know that
eg :
getName(){
return firstName+lastName;
}
or
getData(){
// code to convert byte to Mb or whatever you like to represent
}
Use of accessors to restrict direct access to field variable is preferred over the use of public fields, however, making getters and setter for each and every field is overkill and considerd as not a good practice. It also depends on the situation though, sometimes you just want a dumb data object. Accessors should be added for field where they're really required. See this link to know more about it Getter Setter: To Use or Not to Use.
I can't find a logical reason behind having a private variable with a getter and a setter that does nothing but directly handling the value being preferable to having a public variable.
Consider that any additional code that you put into getters and setters adds to complexity and also needs to be tested. For a small system which is fully controlled by you, there may be little benefit in using getters and setters. Use your professional judgement. You may not need the future proofing and added complexity. Or it may be more important to you to have the efficiency and simplicity of direct access.
Personally, I think that getters and setters are over-used. For a small system which is fully controlled by you, direct access may be the way to go.
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)
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...
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.
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
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.
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.
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:
The field's value should be accessible to client code, using a public interface.
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.
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.
Accessing protected fields from a subclass is one of the ways that inheritance violates encapsulation. Using the public API is better for this reason.