This has been said before: Protected variables are evil (blog post gone). But apparently as I’ve been doing some debugging into the Eclipse code I’m reminded it needs saying again.
Let’s suppose we write a base class
public class SimpleBase { protected Object value = new Integer(10); public printValue() { system.out.println(value.toString()); } } public class Derived extends SimpleBase { public Derived() { value = null; } } ... main() { new SimpleBase().printNumber(); new Derived().printNumber(); }
The output of this is:
10 NullPointerException
This output is expected. The problem: the designer of SimpleBase relied on the author of the Derived behaving well and only setting value to a valid value. I prefer to trust no one. In our simple case this was easy to debug. But in more complex code is like finding a needle in haystack – slow, time consuming and completely unnecessary.
Most examples of protected variables (e.g. Eclipse: TextCellEditor) that I’ve found could easily be replaced by a protected getter. Now the derived class can’t damage the base class data.
In the rare cases the derived class really needs to change something the base class: provide a setter. The setter can do some simple argument checking: null, empty string, -1, …
However I’ve never personally found a case where a derived class really needs to set something on the base class.
Is protected final any better? On the surface it is. However I assume that some later developer might strip away the final part to solve some other problem and boom you’re back at square one with a difficult to diagnose bug.
The final point that most people don’t remember protected is really just public lite. Not only do your derived classes get access to your protecteds but so other classes in the same package.
In short there is no sane or safe reason for protected variable and no circumstance where they can’t be replaced with getters (or maybe a setter) – so don’t use them.
This rant brought to you by the Eclipse foundation whose code has more than a few protected member variables. Again I ask my friends at Eclipse – why did anyone think this was a good idea?
This is the second in an occasional series of posts on really bad coding practices. The first was Don’t call overridable methods in constructors.
BTW I really like Eclipse I just wish that there was better code quality. Really it doesn’t take any more time and effort.
Mark Levison has been helping Scrum teams and organizations with Agile, Scrum and Kanban style approaches since 2001. From certified scrum master training to custom Agile courses, he has helped well over 8,000 individuals, earning him respect and top rated reviews as one of the pioneers within the industry, as well as a raft of certifications from the ScrumAlliance. Mark has been a speaker at various Agile Conferences for more than 20 years, and is a published Scrum author with eBooks as well as articles on InfoQ.com, ScrumAlliance.org an AgileAlliance.org.
Greg says
State is part of the interface of a class. This is very frequently forgotten, since it doesn’t get typed in most languages.
The only guarantee that derived classes adhere to that part of your interface is to make the state private. Protected accessor methods are better but no panacaea – the method must take responsibility for making sure state doesn’t change in a way that breaks your interface.
Greg says
Urgh, I was unclear there: Protected accessors are better than protected variables, but that doesn’t make them good. 🙂 Private is the way. I try not to let state creep into my interfaces at all, but if you must have it, for sanity’s sake don’t let derivers touch it behind your back.
Curt Cox says
I think we all pretty much agree here. I think the best advice on this general topic is given in “Effective Java”. Design for inheritance and document it–or prohibit it.
Mark Levison says
Greg – we’re agreed in principle I’m just tired of debugging code that doesn’t obey the contract.
I find if we’re paranoid fewer mistakes slip through the cracks.