views:

299

answers:

2

Please note I am specifically referring to the fact that dot notation is being used on class methods, not instance methods.

Out of curiosity, I wanted to see what would happen if I tried to use Objective-C 2.0 dot notation syntax on a class method. My experiment was as follows:

#import <Foundation/Foundation.h>

static int _value = 8;

@interface Test : NSObject
+ (int) value;
+ (void) setValue:(int)value;
@end

@implementation Test
+ (int) value
{
  return _value;
}
+ (void) setValue:(int)value
{
  _value = value;
}
@end

int main(int argc, char * argv[]) {
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  NSLog(@"Test.value: %d", Test.value);
  NSLog(@"[Test value]: %d", [Test value]);
  Test.value = 20;
  NSLog(@"Test.value: %d", Test.value);
  NSLog(@"[Test value]: %d", [Test value]);
  [Test setValue:30];
  NSLog(@"Test.value: %d", Test.value);
  NSLog(@"[Test value]: %d", [Test value]);
  [pool release];
  return 0;
}

I was surprised to see that this compiled, let alone executed with what is, I suppose, correct behavior. Is this documented somewhere, or just a fluke of the compiler?

I compiled using GCC on Mac OS X 10.6:

gcc --version: i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5659)

compile using: gcc ObjCClassDotSyntax.m -framework Foundation -o ObjCClassDotSyntax

run: ./ObjCClassDotSyntax

output:

2010-03-03 17:33:07.342 test[33368:903] Test.value: 8

2010-03-03 17:33:07.346 test[33368:903] [Test value]: 8

2010-03-03 17:33:07.351 test[33368:903] Test.value: 20

2010-03-03 17:33:07.352 test[33368:903] [Test value]: 20

2010-03-03 17:33:07.353 test[33368:903] Test.value: 30

2010-03-03 17:33:07.353 test[33368:903] [Test value]: 30

+7  A: 

This is correct behavior. foo.method is syntactic sugar for [foo method]—a straight conversion with identical semantics. Similarly foo.prop = bar is syntactic sugar for [foo setProp:bar], again with identical semantics. This transformation is implemented in the compiler. Thus you can use dot notation to call 0-parameter methods as in foo.doSomething instead of [foo doSomething]. Of course, if you do this, you are evil.

The fact that the callee is a class instance doesn't mater because in Objective-C, classes are also objects. Using dot notation on a class calls the parameterless method on that class.

Dot notation is described in the Objective-C Programming Language document.

Barry Wark
+1 for Evil. Seriously though, would it be bad to use the sweet syntatic sugar, and if so, why?
andy
I am specifically referring to the fact that dot notation is being used on *class* methods, not *instance* methods. Is this still expected behavior?
Eric
The fact that it's a class method makes no difference. As Barry pointed out, using dot notation is exactly the same as calling the methods using square braces.
Rob Keniger
One thing which always bothers me in Objective-C is that the class name itself doesn't work as a stand-alone expression. Try `NSLog(@"%@",Test)` here... it complains. So it's quite surprising to me that `Test.value` works here.
Yuji
But where is this documented? I thought that you had to use the @property syntax to specify that you would be using dot syntax notation, otherwise you would get an error from the compiler (at least, this is the case for instances)
Eric
Brings up the question of the difference between a read-only property with a getter method (x = [foo property] or x = foo.property) and other non-void general methods (y = [foo doSomething]).Is there a real linguistic difference? Or is it up to the programmer to use these appropriately and never use y = foo.doSomething?
mbmcavoy
@Yuji, `Test.value` works because `[Test value]` works. I agree that not being able to use `Test` instead of `[Test class]` is a wart, but that's an unrelated issue.
Barry Wark
@andy The reason not to use the sugar for calling non-accessor methods is that it breaks the semantic meaning of @properties. It's legal in the language, but it implies something to *people* who read your code that is different from the effect of that code. Not cool.
Barry Wark
@mbmcavoy It's up to the programmer to not abuse dot notation. The language doesn't care--this is true syntactic sugar. But *source code* is for people, not run-times. Others (including future you) have to read your code and abusing dot notation makes that job more painful. Just Don't Do It.
Barry Wark
@Eric That's not true! Dot notation works on any properly-named accessors, even in instances. Properties are a separate concept from dot notation. As Barry Wark said, `foo.bar` is exactly identical to `[foo bar]`--that applies whether foo is a class or an instance, and whether bar is defined by @synthesize or by hand, or even if bar is an action or other non-accessor method.
andyvn22
A: 

In the "evil but it works" category, I've been known to use convenience constructors with the dot notation once in a while, such as NSMutable *myArray = NSMutableArray.array

NSResponder
Man, that is totally evil. I don't know whether to upvote or downvote for evilness....
Dave DeLong
Of course, you can also do "myView.setNeedsDisplay;" or any other message that doesn't take any parameters.
NSResponder