I think the subject is much less arguable if it’s about getting/setting some data from outside the class (right, properties should be used). So in this post we will focus on private and protected class members.
Does it Matter?
It might sound not that important – why can’t we just make a random decision and stick to it? Well, properties / ivars are something that is used all the time. I think it’s a good practice to sometimes pay attention to how we do common tasks. It’s natural, and it’s a good way to increase efficiency as well – even a slight improvement sums up to something quite significant within time.
Obviously, using properties will cost you some CPU because additional methods get called. But this is so insignificant in 99.99% of the cases! And for the rest 0.01% – use ivars, but be aware that the improvement you get is almost nothing compared to other optimizations you usually can add.
Properties have attributes, and they are quite useful. However, I think they are only useful if used from outside the class. Let’s discuss two of them:
- readonly – A readonly property means it can only be set by the instance. And to be useful, the instance should set it at least once in the code. Which means you actually have to write to the ivar. (There’s one exclusion: you can have a read-only property implemented without an ivar, but then it’s just a method and the @property line is not needed.) So if you are accessing the ivar once, why not just use it everywhere?
- copy – Sometimes, you must copy something – convert mutable to immutable or save a block. But using the copy attribute for private properties actually won’t make your code more readable. I prefer to just call the copy method before the assignment if it’s required.
If you use ivar / property inside a class, you usually know what it’s purpose is and how it should be accessed. So I think the attributes don’t add anything in favor of private properties.
Replacing Getters/Setters With Custom Implementations
I worked once in a team with a convention to not use ivars. Don’t get me wrong – code conventions are often a good thing, I just don’t agree with one of the main reasons I got for this one: “if required, we can override the default getter/setter later”. Come on, how often do you override an inner property getter/setter? And also, the refactoring would take almost no time, because all the usages are in the same file.
How about protected members? In objective C, there’s access control for instance variable, but not for methods. Once you defined a method (or property) it can be called (accessed) from anywhere, so in theory there are only public properties. But in my opinion it’s good enough to define a property in .m to consider it private. And what if you need protected? There’s a trick: for a class SomeClass you define an additional .h file, call it SomeClass_protected.h, and put there all the protected properties. It’s a bit ugly, but this case is quite rare actually, at least for me (I personally think that using inheritance causes troubles more often that helps, and there are really few cases where I would use it).
On the other hand, by using properties you can easily switch them between public and private (and like it was already mentioned, it’s very bad to use public ivars). The need to switch between public and private is questionable and the refactoring is not that hard if switching between properties and ivars, but it has to be said to veil my bias :-).
Ease of Access
Personally, I’m quite convinced who is the winner here. Let’s take a look at the following example:
[listCopy addObject:self.nextEntry]; _list = listCopy.copy;
Look at nextEntry and at list. What is public and what is private? While self.nextEntry is a property, it’s private – but you can’t know it until you check the definition! And what about _list? It’s actually a public, but read-only property, so we access it via its ivar to assign a new value.
I think it’s quite confusing. While you can probably do nothing about _list, using ivars for internal members would at least improve our situation with nextEntry. It would be called _nextEntry and in most cases it would mean it’s private.
You can of course use _ in private properties to get over it, though I think I never saw someone using private properties that way. Either this issue doesn’t bother people, or may be those who are bothered by this just use ivars.
The Before-ARC pain
It seems so far that there’s no something so much better is using private properties over ivars. Then why do so developers use them? I think the only reason is the non-ARC history. Before ARC, you had to retain-release every object referenced in your class. And private properties were solving it really nice! Instead of
[_myList release]; _myList = [[NSArray arrayWithObject:@”abc”] retain];
you would just write:
self.myList = [NSArray arrayWithObject:@”abc”];
Just imagine what would happen if ARC was there from the beginning. Anyone starting programming in Objective C would just use ivars, like in other languages, so using private properties would never become such a popular practice.Much better, right?