tags:

views:

215

answers:

4

is self not completely interchangeable with this in C++?

It seems to work with message passing ( [ self sayHi ] would work within any method there ).

I don't quite understand why I can't use self to access private members of an object (in the example below, I show I can't use self.width)

#import <Foundation/Foundation.h>


// Write an objective-c class
@interface Rectangle : NSObject
{
  int width ;
}

-(int)getWidth;
-(void)setWidth:(int)w;
-(void)sayHi;
-(void)sayHi:(NSString*)msg ;
@end

@implementation Rectangle

-(int)getWidth
{
  // return self.width ; // ILLEGAL, but why??
  // why can't I return self.width here?
  // why does it think that's a "method"?
  return width ;
}
-(void)setWidth:(int)w
{
  // self.width = w ; // ILLEGAL
  // again here, i CAN'T do self.width = w ;
  width = w ;
}
-(void)sayHi
{
  puts("hi");
}
-(void)sayHi:(NSString*)msg
{
  printf( "Hi, and %s\n", [ msg UTF8String ] ) ;
}

@end



int main (int argc, const char * argv[])
{
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];


  Rectangle* r = [ Rectangle alloc ] ;
  [ r sayHi ] ;
  [ r setWidth:5 ] ;
  printf( "width is %d\n", [ r getWidth ] ) ;


  [pool drain];
  return 0;
}

+4  A: 

You can't use self.width because it's not a property. self.width = w is shorthand for [self setWidth:w]; which was introduced in Objective-C 2.0. Try adding @property int width; above your method prototypes in the interface file, and at the top of your implementation file under the @implementation line, add @synthesize width;. That should allow you to use self.width, but it would no longer be a private variable.

You could also use @property (readonly) int width; to only generate a 'getter' method for width, but I doubt that's what you want. For more options you can pass to @property, check this documentation page.

Also, like Cliff said, getVar isn't convention in Objective-C. Instead, you just use the name of the variable you want to expose. The get prefix is usually used for when you're returning some form of raw data, as far as I know.

Jorge Israel Peña
Oh re-he-he-heally... sweet. So dot notation simply translates down to that square bracket stuff. Thanks! This answer helped.
bobobobo
Apple's Cocoa Coding Guidelines (http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html#//apple_ref/doc/uid/20001282) state that the `get` prefix should only be used when returning multiple values indirectly through pointers given in the method arguments. For example, NSColor has a method named `getRed:blue:green:alpha` that returns the color's RGBA components through the given `CGFloat` pointers.
htw
Sort of. Dot notation is actually entirely orthogonal to `@property`. The reality is that Objective-C objects are never on the stack (save for Blocks, but that is a very special case) and, thus, `.` to access members doesn't make sense.
bbum
+3  A: 

self.width is shorthand for [self width] and since you have not defined a width method it will be illegal. The getters in ObjC do not start with "get" by convention as they would in other languages like Java. Also I've heard from other experts (though I don't understand why) that it's not a good idea to use the property syntax from within the object that owns the proerty. From what I heard it causes some kind of a gotcha with Key Value Coding. In your example if you want to define a custom getter/setter then just reference the value directly without the self qualifier. It probably makes sense to use the getter/setter or dot notation everywhere else for good encapsulation.

Cliff
+1  A: 

self in Objective-C, like this in C++, is a pointer to the current object. So to access a field through self, you would do self->width (just as you would do this->width in C++)

newacct
+11  A: 

The other answers are almost correct, but not quite.

In Objective-C, no object [save for Blocks, but that is a very very special case] are ever on the stack. Thus, self.width doesn't make sense.

However, self->width does work. Since self is a reference to what is effectively a structure allocated on the heap, using the -> operator to get at the member variables makes sense.

But, in the context of Objective-C, it generally doesn't make sense, either. That is, Objective-C generally assumes a philosophy of preserving encapsulation. That is, you don't generally reach into an object and muck with the instance variables -- the internal state -- directly. Instead, you use the accessors to get/set the state. By doing so, the object (and subclasses) can customize getter/setter behavior, as needed. (This includes such mechanisms as Key-Value Observing and Key-Value Coding).

That self.width happens to equate to [self width] or [self setWidth: ...something...] is fallout from the above. That is, the . operator for accessing members of Objective-C class instances was not otherwise used and could be overloaded as a short hand for property access.

However, there is little difference between property access and invoke the getter/setter method. Thus, dot notation is synonymous with method invocation.


Within the context of your code, instance variables are transparently accessible within your classes implementation and without prefix.

Thus, you would use width = 5.0; instead of self.width = 5.0;, typically. Of course, the latter does equate to a method call with Objective-C 2.0 for reasons stated above.

bbum