instance variable/ method argument naming in Objective C
Asked Answered
S

5

15

What conventions are people here following for naming of instance variables and method arguments - particularly when method arguments are used to set ivars (instance variables)?

In C++ I used to use the m_ prefix for ivars a lot. In C# I followed the convention of disambiguating purely by use of this. for ivars. I've since adopted the equivalent in C++ too (this->).

In Objective C I've tried a few things but none have really seemed satisfactory.

Unless someone suggests something really nice I am resigned to the fact that I'll have to compromise (but please, don't make me use the the prefix for args!), so I'm interested to hear what the majority say - especially from those who have been using ObjC for a while.

I did some due diligence before posting this and a couple of good resources I found where:

They give me some ideas, but I'm still keen to hear what others are doing.

[edit] Just to clarify: It's specifically how you distinguish ivars from method args that I'm looking for - whether that's through prefixes or some other technique.

[edit 2] Thanks for all the responses and discussion points. I'm not closing this, but will just say that, as I indicated in my comments to the accepted answer, I've gone with the convention of prefixing init args with the (and setter args with new, which I was doing anyway). This seems to be the best balance of forces - even if I'm not keen on the aesthetic myself.

Scorecard answered 14/2, 2009 at 23:14 Comment(0)
V
17

As you've noted, the Cocoa style is to use method argument names like theValue if the argument name will conflict with an instance variable. There shouldn't be many times that this comes up in Objective-C 2.0 style code, however. The assumption is that you shouldn't (usually) be accessing instance variables directly. Mostly this is because doing so circumvents the Key-Value Observing machinery in Cocoa. Rather, the expectation is that you'll access and mutate properties via getter/setter methods. In Objective-C 2.0, it's easy to declare these properties and automatically @synthesize the getters/setters, so there's not much excuse for not using them. In fact, on 64-bit systems, the runtime will automatically create the instance variables for you, obviating the need to declare them and reducing the urge to use them.

The only time you should be accessing instance variables directly is in -init and -dealloc methods:

@interface MyObject : NSObject 
{
  id ivar;
}

@property (retain,readwrite) id ivar; //or whatever retain/copy/assign and read/readwrite makes sense
@end

@implementation MyObject
@synthesize ivar;

- (id)initWithIvar:(id)theIvar {
  if(self = [super init]) {
    ivar = theIvar;
  }

  return self;
}

- (void)dealloc {
  [ivar release];
}

The reason the ivar should be used directly in these cases is beacuse the getter/setter may have side effects that depend on a fully initialized instance, thus making them dangerous in -init and -dealloc where the state of the object is fully initialized. In all other cases, you should be using self.ivar (or [self ivar] and [self setIvar:newValue]).

It would seem that methods other than -initWithXX shouldn't have the naming conflict. If they do, shouldn't they be refactored to not have that parameter or for the Class to not have the instance variable?

This leaves just the -initWithXX methods where you would often find a conflict between arguments and ivars. For this case, you can use any of the approaches you mention if you really can't stand the Cocoa style. Prefixing with _ works and is relatively common (I believe the @synthesize'd setters and getters will automatically do the right thing in this case, but you may have to explicitly set the _ivar as the backing).

Veery answered 15/2, 2009 at 5:19 Comment(13)
Thanks Barry. The trouble with using accessors within the class implementation is that they add a significant overhead - which you may be able to ignore in desktop apps, but on the iPhone they can add up. Also, as you say, they may have side-effects that you don't want from within the impl...Scorecard
...[cont]. That said it is mostly in init methods that the clash occurs (in mutators I usually use newX or similar anyway). Since the consensus seems to be on the or a as a prefix for the arguments I can perhaps live with that just within init methods. That keeps the ivars cleaner.Scorecard
I would verify that property access vs. direct ivar access is an unacceptable performance hit. I clarified above why you have to access ivar directly in init/dealloc. Otherwise, it seems dangerous to have direct access along side property access since it muddies the semantics of the ivar state.Veery
I hear ya. Of course most of the time it's ok - but there have been one or two places that it's been an issue. I'd rather adopt a convention that I don't have to make too many exceptions to.Scorecard
Direct access by impl and property access by outside users is pretty much the established idiom in most languages - although I accept that there are compelling cases for making all access go via accessors by default. I haven't yet bought into that fully, however.Scorecard
It seems that property access is more the norm in dynamic languages (e.g. Python, Ruby, ObjC). Since ObjC 2.0 explicitly removes the ability to do self->isa->..->ivar ala C++ this->ivar, I think this is a case of different languages making different trade offs...Veery
...[cont]. Objective-C's designers seem to have chosen dynamicism (including auto-generated ivars for @properties) over odd initializer argument names. I'm sympathetic (I think "theIVar" is stupid too), but it's something I've gotten over in an otherwise very nice language.Veery
Not sure I get your "self->isa->..->ivar ala C++ this->ivar" comment, but I agree with the different languages making different trade-offs. I've also conceded to using theArgName in initializers and remain alive and well :-) Thanks for making some good points, even if I don't agree with them all!Scorecard
self (type id) is a pointer to a struct objc_object (objc.h)Prior to ObjC 2.0, you could traverse this struct to get to the ivars of the instance. With ObjC 2.0, this implementation is hidden to support automatic instance variable creation, among other reasons.Veery
Oh I see. I'm not sure I'd like to use that as a name scoping device anyway :-) (self-> or this-> yes, but going even one more level of indirection deep would be OTT).Scorecard
Yes, absolutely. I mentioned it just for completeness, but I think settling theArgName is still the best option, unfortunately.Veery
There's another reason why properties should be avoided in dealloc, which I think is more compelling than the fact that setters may rely on state that's not valid here. Setting properties will trigger KVO notifications, which is something that you definitely want to avoid in -dealloc.Dripstone
I really really really hate "the" as in "theValue". So what I use is "newValue" in mutators and "initValue" in initializers. (Except I absolutely loathe wimpyCaps, so what I actually write is "new_value" and "init_value".)Gibran
O
2

To complete all known Objective-C styleguides here is the google version. What they do is to add an underscore after the the member varname. For instance BOOL isActive_;.
So make a choice and stick with it. I also prefer the "_" prefix for my apps.

Otterburn answered 16/2, 2009 at 7:5 Comment(0)
M
1

Here's how Apple does it.

Murdoch answered 14/2, 2009 at 23:37 Comment(6)
Thanks wfarr. However that doesn't actually describe a naming convention for ivars or method arguments (other than to say, "Make sure the name of the instance variable concisely describes the attribute stored.")Scorecard
Your edit clarified things. I believe I've seen people just use _ as a prefix to differentiate ivars from method args.Murdoch
the trouble with _ as a prefix is that it's reserved by Apple, and they use it in a number of base classes (info on that in some of the links I gave).Scorecard
Apple does not reserve the underscore prefix for instance variable names. Only for method names.Caldwell
ANSI C reserves ALL identifiers starting with a _ for themselves, the compiler, and/or the OS. If you use it Apple may not invalidate your code, the next C standard might. Or (smaller chance) the next compiler.Bradbradan
technically only "_" with a capital letter following is reserved in C. (also a double underscore is reserved). An underscore followed by a lower-case letter is actually ok.Savarin
O
1

The sample code produced by Apple usually uses a "_" prefix. I think I also saw some using mFoo or m_foo. Some don't bother with prefixes at all and just use a normal name, however that gets confusing later on. In general when defining method parameters, the naming convention is to use an "a", "an", "the" or "new" prefix. For instance:

@interface Foo : NSObject {
    id _bar;
}
@property (nonatomic, retain) id bar;

- (id) initWithBar:(id)aBar;

@end

@implementation Foo
@synthesize bar = _bar;

- (id) initWithBar:(id)aBar {
    self = [super init];
    if(self != nil) {
        _bar = aBar;
    }
    return self;
}

@end

I find that this convention works quite well. I used to not bother with the prefix but that made things confusing sometimes. Using a prefix clearly indicates that it's an instance variable. The @synthesize bar = _bar convention is used by Apple in their (iPhone) sample code.

The instance variable would not typically be used anyway, so if you find the "_" prefix annoying it doesn't matter, because you'd use [self bar] (or self.bar if you're into that kind of thing) anyway.

Osmometer answered 15/2, 2009 at 6:19 Comment(5)
Thanks sebnow. Apple reserve the underscore prefix for themselves to avoid name conflicts (see: developer.apple.com/documentation/Cocoa/Conceptual/… - and the end of "Typographic Conventions"). I'd prefer to avoid itScorecard
Apple does not reserve the underscore prefix for instance variable names. Only for method names.Caldwell
@Chris: In that article it says, "Avoid the use of the underscore character as a prefix meaning private, especially in methods. Apple reserves the use of this convention" - note especially in methods - not only in methods...Scorecard
...[cont] I interpret that (in the context) as saying, "this is reserved in the case of method names, but it's also a guideline not to use it for other names too". So I'm not saying you're wrong - and I recant my use of the word "reserved" - but it still warns against using itScorecard
The ISO C standard says that all "symbols" (and a symbol can be pretty much anything, a variable, a function, etc.) that start with an underscore, followed by a capital letter are reserved for compiler internal use. That means, if you start your ivars with an underscore, making the first letter after that a capital one would even violate the C standard. Don't use underscores at the beginning of symbol names, it's pretty much never a good idea.Lecompte
L
1

Obj-C does not define "style" as strictly as many other languages, this might be a good thing or rather a bad one, but it means you are on your own to find a good coding style most of the time.

You can also access variables in Obj-C via self. So if you have an instance variable test, you can access it via self->test, this is legit and will always work. It's not beautiful in the eyes of most Obj-C programmers, though. It gives away the "secret", that objects are in fact just structs (more precisely, object refs are pointers to structs) and instance vars are in fact struct members. Not that this is really secret, but Obj-C programmers seems to prefer to "hide" this fact in their code.

Using underscore "_" in the name is a very bad idea. Someone here pointed out that Apple reserves underscore for their code, but actually GCC already reserves underscore for symbol names. More precisely, already the ANSI-C standard says that variables starting with either two underscores or one underscore and an upper case letter are reserved for the compiler's internal usage. So using one underscore is in theory valid, but accidentally start the name with an upper case letter and it becomes invalid.

What I tried so far was using the prefix my, myName instead of name, and using the prefix self, selfName instead of name; looks both somehow strange at first, but doesn't look too bad in a huge piece of code. At least immediately hits the eye as being "different". I also just tried a single "i", iName instead of name (or iname instead of name), but I was not very satisfied with that solution.

I never wasted time thinking about method parameters, though. Because it does not really matter. Those are variables like any other variables, unless they are declared constant. They can be even re-used for other purposes within the method, because it will have no affect on the caller. E.g.

- (NSImage *)loadImage:(int)imageNumber
{
  NSImage * res;

  // Some code that assigns a value to res
  // ...  

  // Re-use imageNumber for a different purpose
  for (imageNumber = 0; ...; ...) {
     // Some code
  }

  return res;
}

I see no problem with that code. Why would I have to declare a second stack variable for that as long as the name still makes sense (if I'm not iterating over images by number in the for loop, the name makes no sense of course, in that case I would use a different variable for it - compiler may in fact reserve only one int on stack for both).

Lecompte answered 9/12, 2009 at 15:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.