Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

instance variable/ method argument naming in Objective C

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:

  • This style guide (briefly mentions my subject)
  • This thread (a lot of ex C++ coders in there)

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.

like image 563
philsquared Avatar asked Feb 14 '09 23:02

philsquared


People also ask

What is instance variable Objective C?

An instance variable is a variable that exists and holds its value for the life of the object. The memory used for instance variables is allocated when the object is first created (through alloc ), and freed when the object is deallocated.

Can you use instance variables as parameters?

There's no problem with giving parameter names and instance variable names the same name. But Java has to pick whether it is an instance variable or a parameter variable. Either way, it doesn't do what you think it should do. It doesn't initialize the instance variables with the values of the parameter variables.


5 Answers

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).

like image 171
Barry Wark Avatar answered Sep 18 '22 19:09

Barry Wark


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.

like image 32
kompozer Avatar answered Sep 21 '22 19:09

kompozer


Here's how Apple does it.

like image 29
wfarr Avatar answered Sep 19 '22 19:09

wfarr


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.

like image 41
sebnow Avatar answered Sep 20 '22 19:09

sebnow


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).

like image 33
Mecki Avatar answered Sep 21 '22 19:09

Mecki