20

Note, I'm specifically referring to the fact that dot notation is being used with class methods, not instance methods.

Out of curiosity, I wanted to see what would happen if I tried to use Objective-C dot notation syntax with 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 was 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
Lebyrt
  • 1,376
  • 1
  • 9
  • 18
Eric
  • 269
  • 2
  • 5
  • And, I wonder, why does Xcode **not autocomplete** when dot syntax is used for class methods? If it truly is syntactic sugar, e.g. `foo.prop` purely translates to `[foo prop]`, then Xcode should not distinguish between class methods and instance methods. – Timo Jan 14 '13 at 11:01

3 Answers3

33

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
  • 107,306
  • 24
  • 181
  • 206
  • 10
    +1 for Evil. Seriously though, would it be bad to use the sweet syntatic sugar, and if so, why? – andy Mar 04 '10 at 00:03
  • 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 Mar 04 '10 at 00:13
  • 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 Mar 04 '10 at 00:16
  • 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 Mar 04 '10 at 00:17
  • 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 Mar 04 '10 at 00:19
  • 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 Mar 04 '10 at 00:21
  • @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 Mar 04 '10 at 00:51
  • 6
    @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 Mar 04 '10 at 00:52
  • 1
    @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 Mar 04 '10 at 00:54
  • 3
    @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 Mar 04 '10 at 01:01
  • 9
    I'd strongly disagree with the evil declaration, or at least demand an exception be carved out. If you have a method that returns a property like feature (i.e. a noun, not a verb), it's easier for future programmers to comprehend the code. Methods that merely calculate some value (nouns) rather that mutating values or changing state are better accessed via the dot interface for quick code comprehension. Verb methods (which generally change state) should always be accessed via bracket notation. – Prometheus Jan 02 '13 at 01:10
  • 1
    @BarryWark: If it's about readable and logical source code (which I agree it is), then it depends on the *function* of the method: `UIApplication.sharedApplication` calls a *getter method* on the class. Sure, that getter is not implemented using the @property shorthand, but that's no more than a shorthand anyway. Here is a method that serves as a getter, and I consider the code very readable and logical if `UIApplication.sharedApplication` is used. If I'm not mistaken, this would be a *static property* in many other languages. `NSArray.array`, in that sense, is illogical (*factory method*). – Timo Jan 14 '13 at 11:13
  • 1
    Even though I secretly enjoy NSArray.array for not needing any pesky brackets. :> I always get in trouble for forgetting the leading bracket! – Timo Jan 14 '13 at 11:15
  • Dot notation is just cleaner and flows better when typing (not to mention is already the accepted norm). Apple should just migrate entirely to dot notation and be done with the nonsense smalltalk-style message passing, imo. – devios1 Jul 04 '13 at 18:18
  • 2
    Coming from Ruby at first I believed that the idea that "Dot syntax for method calls are evil" was absurd. But now that I have delved in for about 6 months into objective-c, I came across my first example of dot syntax being used improperly, and it left me quite confused at first. My preference is that I won't even use it on accessor method, I will just use it on @properties. That way, I instantly know WHAT is a property and WHAT is not without having to look at the header file. It seems the most pragmatic in my opinion. – Sean Larkin Apr 25 '14 at 12:20
  • 1
    Sometimes I use square brackets as a *sign to myself and others* that the accessor has a lot of code in it that could mutate something or change something outside of the property we're accessing. For example, `DatabaseMediator.persistentStoreCoordinator` could mislead someone into not realizing that this does not just return the value of persistentStoreCoordinator but runs a 100-line method which does all kinds of cool things. So I put [DatabaseMediator persistentStoreCoordinator] as a reminder that this is a *defined method that does lots of stuff*. It's just a code readability thing. – CommaToast Jun 14 '16 at 16:56
12

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 NSMutableArray *myArray = NSMutableArray.array

NSResponder
  • 16,861
  • 7
  • 32
  • 46
  • 17
    Man, that is totally evil. I don't know whether to upvote or downvote for evilness.... – Dave DeLong Mar 04 '10 at 18:59
  • Of course, you can also do "myView.setNeedsDisplay;" or any other message that doesn't take any parameters. – NSResponder Mar 04 '10 at 19:26
  • 3
    You are so evil, letting my programmers heart getting infected with your ideas. My boss will beg me on his knees. All the people that will see my code and cry, 'cause I also will be a bad guy. – Binarian Oct 06 '12 at 16:18
0

The Underscore library further abuses this syntax by returning blocks from class methods, resulting in code like this:

NSArray *elements = Underscore.array(array)
    .flatten
    .uniq
    .unwrap;

To understand how this works, look at the definition of Underscore.array:

+ (USArrayWrapper *(^)(NSArray *))array
{
    return ^(NSArray *array) {
        return [USArrayWrapper wrap:array];
    };
}

So:

Underscore.array(array) 

...is equivalent to this:

NSArray *array = @[];
USArrayWrapper * (^arr)(NSArray *) = [Underscore array];
USArrayWrapper *result = arr(array);
Wayne
  • 59,728
  • 15
  • 131
  • 126