2010-03-03 3 views
19

Обратите внимание, что я специально ссылаюсь на то, что точечная нотация используется с методами класса, а не с методами экземпляра.Objective-C-точка с использованием методов класса?

Из любопытства я хотел посмотреть, что произойдет, если я попытаюсь использовать синтаксис нотации Objective-C dot с помощью метода класса. Мой эксперимент был следующим:

#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; 
} 

я с удивлением увидел, что это был составлен, не говоря уже казнены с тем, что, я полагаю, правильное поведение. Является ли это документированным где-то, или просто случайностью компилятора?

Я скомпилированы с использованием GCC на 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 
+0

И, интересно, почему Xcode ** не автозаполнение ** когда точка синтаксис используется для методов класса? Если это действительно синтаксический сахар, например. 'foo.prop' чисто переводит на' [foo prop] ', тогда Xcode не должен различать методы класса и методы экземпляра. – Timo

ответ

31

Это правильное поведение. foo.method - синтаксический сахар для [foo method] - прямое преобразование с идентичной семантикой. Аналогично foo.prop = bar является синтаксическим сахаром для [foo setProp:bar], опять же с идентичной семантикой. Это преобразование реализовано в компиляторе. Таким образом, вы можете использовать для обозначения 0-параметрических методов, как в foo.doSomething вместо [foo doSomething]. Конечно, если вы это сделаете, вы найдете evil.

Тот факт, что вызываемый экземпляр экземпляра класса не работает, поскольку в Objective-C классы также являются объектами. Использование точечной нотации в классе вызывает метод без параметров в этом классе.

Точечная нотация описана в документе Objective-C Programming Language.

+9

+1 для зла. Серьезно, правда, было бы плохо использовать сладкий синтаксический сахар, и если да, то почему? – andy

+0

Я специально ссылаюсь на то, что точечная нотация используется в методах * class *, а не в методах * экземпляра *. Ожидается ли такое поведение? – Eric

+0

То, что это метод класса, не имеет значения. Как заметил Барри, использование точечной нотации точно так же, как вызов методов с использованием квадратных скобок. –

10

В «зло, но это работает» категория, я, как известно, использовать удобные конструкторы с точечной нотации раз в то время, как NSMutableArray *myArray = NSMutableArray.array

+15

Человек, это совершенно зло. Я не знаю, стоит ли повышать или понижать уровень зла .... –

+0

Конечно, вы также можете сделать «myView.setNeedsDisplay;» или любое другое сообщение, которое не принимает никаких параметров. – NSResponder

+3

Вы настолько злы, что мои программисты начинают заражаться вашими идеями. Мой босс попросит меня на колени. Все люди, которые будут видеть мой код и плачут, потому что я тоже буду плохим парнем. – Binarian

0

The Underscore библиотечные дальнейшие злоупотребления этот синтаксис, вернувшись из блоков методы класса, в результате чего в коде, как это:

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

Чтобы понять, как это работает, посмотрите на определение Underscore.array:

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

Итак:

Underscore.array(array) 

... эквивалентно следующему:

NSArray *array = @[]; 
USArrayWrapper * (^arr)(NSArray *) = [Underscore array]; 
USArrayWrapper *result = arr(array);