tags:

views:

3085

answers:

8

Should you ever use protected member variables? What are the the advantages and what issues can this cause?

+22  A: 

Should you ever use protected member variables?

Depends on how picky you are about hiding state.

  • If you don't want any leaking of internal state, then declaring all your member variables private is the way to go.
  • If you don't really care that subclasses can access internal state, then protected is good enough.

If a developer comes along and subclasses your class they may mess it up because they don't understand it fully. With private members, other than the public interface, they can't see the implementation specific details of how things are being done which gives you the flexibility of changing it later.

Sorry if this rambled a bit.

Just my 2 cents.

Allain Lalonde
Can you comment on performance of protected variables vs a private variable with an get/set method?
Jake
I'd say it's not something worth worrying about unless you find through profiling that the bottle neck ends up being the accessors (which it almost never is). There are tricks that can be done to make the JIT smarter about things if it ends up being an issue. In java for example you can hint that the accessor can be inlined by marking it as final.Though honestly, the performance of getters and setters is far less important than dealing with system organization and with the actual performance problems as determined by a profiler.
Allain Lalonde
A: 

For detailed info on .Net access modifiers go here

There are no real advantages or disadvantages to protected member variables, it's a question of what you need in your specific situation. In general it is accepted practice to declare member variables as private and enable outside access through properties. Also, some tools (e.g. some O/R mappers) expect object data to be represented by properties and do not recognize public or protected member variables. But if you know that you want your subclasses (and ONLY your subclasses) to access a certain variable there is no reason not to declare it as protected.

Manu
+10  A: 

The general feeling nowadays is that they cause undue coupling between derived classes and their bases.

They have no particular advantage over protected methods/properties (once upon a time they might have a slight performance advantage), and they were also used more in an era when very deep inheritance was in fashion, which it isn't at the moment.

Will Dean
+2  A: 

In short, yes.

Protected member variables allow access to the variable from any sub-classes as well as any classes in the same package. This can be highly useful, especially for read-only data. I don't believe that they are ever necessary however, because any use of a protected member variable can be replicated using a private member variable and a couple of getters and setters.

Jay Stramel
+6  A: 

Generally, if something is not deliberately conceived as public, I make it private.

If a situation arises where I need access to that private variable or method from a derived class, I change it from private to protected.

This hardly ever happens - I'm really not a fan at all of inheritance, as it isn't a particularly good way to model most situations. At any rate, carry on, no worries.

I'd say this is fine (and probably the best way to go about it) for the majority of developers.

The simple fact of the matter is, if some other developer comes along a year later and decides they need access to your private member variable, they are simply going to edit the code, change it to protected, and carry on with their business.

The only real exceptions to this are if you're in the business of shipping binary dll's in black-box form to third parties. This consists basically of Microsoft, those 'Custom DataGrid Control' vendors, and maybe a few other large apps that ship with extensibility libraries. Unless you're in that category, it's not worth expending the time/effort to worry about this kind of thing.

Orion Edwards
+1  A: 

Most of the time, it is dangerous to use protected because you break somewhat the encapsulation of your class, which could well be broken down by a poorly designed derived class.

But I have one good example: Let's say you can some kind of generic container. It has an internal implementation, and internal accessors. But you need to offer at least 3 public access to its data: map, hash_map, vector-like. Then you have something like:

template <typename T, typename TContainer>
class Base
{
   // etc.
   protected
   TContainer container ;
}

template <typename Key, typename T>
class DerivedMap     : public Base<T, std::map<Key, T> >      { /* etc. */ }

template <typename Key, typename T>
class DerivedHashMap : public Base<T, std::hash_map<Key, T> > { /* etc. */ }

template <typename T>
class DerivedVector  : public Base<T, std::vector<T> >        { /* etc. */ }

I used this kind of code less than a month ago (so the code is from memory). After some thinking, I believe that while the generic Base container should be an abstract class, even if it can live quite well, because using directly Base would be such a pain it should be forbidden.

Summary Thus, you have protected data used by the derived class. Still, we must take int o account the fact the Base class should be abstract.

paercebal
it doesn't break encapsulation anymore than public members do. Its a setting to say that derived classes can use the class' state that isn't exposed to users of the class.
gbjbaanb
@gbjbaanb: You are contradicting yourself "it doesn't break encapsulation anymore than public members do" is different from "[only] derived classes can use the class' state". "protected" is the middle between public and private. So "protected [...] breaks somewhat the encapsulation" is still true...
paercebal
actually, in the c++ language, container adapters like std::stack will expose the underlying container object with a protected variable called "c".
Johannes Schaub - litb
A: 

In general, I would keep your protected member variables to the rare case where you have total control over the code that uses them as well. If you are creating a public API, I'd say never. Below, we'll refer to the member variable as a "property" of the object.

Here's what your superclass cannot do after making a member variable protected rather than private-with-accessors:

  1. lazily create a value on the fly when the property is being read. If you add a protected getter method, you can lazily create the value and pass it back.

  2. know when the property been modified or deleted. This can introduce bugs when the superclass makes assumptions about the state of that variable. Making a protected setter method for the variable keeps that control.

  3. Set a breakpoint or add debug output when the variable is read or written to.

  4. Rename that member variable without searching through all the code that might use it.

In general, I think it'd be the rare case that I'd recommend making a protected member variable. You are better off spending a few minutes exposing the property through getters/setters than hours later tracking down a bug in some other code that modified the protected variable. Not only that, but you are insured against adding future functionality (such as lazy loading) without breaking dependent code. It's harder to do it later than to do it now.

Michael Bishop
A: 

At the design level it might be appropriate to use a protected property, but for implementation I see no advantage in mapping this to a protected member variable rather than accessor/mutator methods.

Protected member variables have significant disadvantages because they effectively allow client code (the sub-class) access to the internal state of the base class class. This prevents the base class from effectively maintaining its invariants.

For the same reason, protected member variables also make writing safe multi-threaded code significantly more difficult unless guaranteed constant or confined to a single thread.

Accessor/mutator methods offer considerably more API stability and implementation flexibility under maintenance.

Also, if you're an OO purist, objects collaborate/communicate by sending messages, not reading/setting state.

In return they offer very few advantages. I wouldn't necessarily remove them from somebody else's code, but I don't use them myself.

richj