Should Protected Fields Be Used in Java?
In this post, we're taking a look at the three different types of Java access level control keywords: Public, Private, and Protected. These three types are used with Java as an access control strategy to limit the scope of access within a program. According to Oracle's Java documentation, "Access level modifiers determine whether other classes can use a particular field or invoke a particular method." These can also be applied to a class's variables or fields. Let's take a quick moment to establish the differences between the three access level modifiers:
- public: Accessible at the class, package, subclass, and world level. Useful for exposing constants. This should only be used when you have a specific reason to do so since exposing things publically gives other areas of your program access to things they might should not have access to and could introduce conflicts or confusion.
- protected: Accessible at the class, package, and subclass level. Useful for exposing something without exposing it too much. Better than using protected because of the tighter access limitations.
- no modifier: This one is a surprise but worth mentioning because you're allowed not to give an access level modifier. When omitted, Java assumes that the access should be class and package.
- private: Accessible only within the class level. This level should be your go-to because unless you need to expose something, you shouldn't. If you're familiar with the principle of least privilege, you'll understand this concept. Unless you need to expose something, you don't need to.
Now let's look at the criticisms of using protected fields. One argument against using protected is that rather than letting child classes directly access fields, getters and setters should always be used to avoid ever letting anything access the internal fields of the class. This is consistent with standard good programming practices because getters and setters are the best practices for exposing member fields. In a best-case scenario, protected fields should be avoided.
Like with most programming opinions, there probably isn't a universal right or wrong answer. In some use cases, it makes sense to never use protected, but in others, it may make sense to use it sometimes.
One argument I've heard before for issues like this is that if you're in a situation where you have to use protected, you've done a poor job designing your program. There may be merit to that argument, especially in an academic or theoretical environment; however, in the real world, we as programmers have to deal with legacy code and code we didn't design. Even though the previous programmer didn't design the program with whatever functionality we're adding in mind, that doesn't mean we can simply not add it. We have deadlines, budgets, and inpatient stakeholders to answer to. It's rarely practical to refactor an entire program just to add one feature when it can be avoided. For that reason, I'm glad the designers of Java have added the protected keyword because it allows us to gain some of the benefits of using private over public when we need to access something in another class.
Adding getters and setters to your classes can very easily eliminate most of the problems associated with needing to use protected fields. Still, with that in mind, in some cases, especially when dealing with legacy code or code you didn't design, protected can be a valuable tool to keep in your Java programming toolkit.
Much like !important should be avoided when writing CSS for web development, protected should be considered a backup tool to use as a last resort when neither public nor private are good options. If you have to use protected when initially writing your program, you probably made a mistake and should revise your program's design in order to follow OOP best practices.
Ultimately using private member fields/variables should be your go-to strategy because you can abstract away the functionality of your class into simple-to-use getter/setter methods. Most programmers expect to be able to access your class members using getters/setters, so exposing the fields/variables publically or protected could cause confusion due to the departure from common practices.