2010-03-03 8 views
19

Nota, me refiero específicamente al hecho de que la notación de punto se está utilizando con métodos de clase, no con métodos de instancia.Notación de puntos en Objective-C con métodos de clase?

Por curiosidad, quería ver qué pasaría si traté de usar la sintaxis de notación de puntos de Objective-C con un método de clase. Mi experimento fue como sigue:

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

Me sorprendió ver que este fue compilado, y mucho menos ejecutada con lo que es, supongo, el comportamiento correcto. ¿Está documentado esto en alguna parte, o simplemente es una casualidad del compilador?

I compilado usando GCC en 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

Y, me pregunto, ¿por qué no Xcode ** ** autocompletado cuando se utiliza la sintaxis con punto para los métodos de la clase? Si realmente es azúcar sintáctica, p. 'foo.prop' se traduce puramente a' [foo prop] ', entonces Xcode no debe distinguir entre los métodos de clase y los métodos de instancia. – Timo

Respuesta

31

Este es el comportamiento correcto. foo.method es azúcar sintáctico para [foo method], una conversión directa con semántica idéntica. De manera similar, foo.prop = bar es azúcar sintáctico para [foo setProp:bar], de nuevo con semántica idéntica. Esta transformación se implementa en el compilador. Por lo tanto, puede usar la notación de puntos para llamar a métodos de 0 parámetros como en foo.doSomething en lugar de [foo doSomething]. Por supuesto, si haces esto, eres evil.

El hecho de que el llamado sea una instancia de clase no importa porque en Objective-C, las clases también son objetos. El uso de la notación de punto en una clase llama al método sin parámetros en esa clase.

La notación de puntos se describe en el documento Objective-C Programming Language.

+9

+1 para Evil. En serio, ¿sería malo usar el dulce azúcar sintáctico, y si es así, por qué? – andy

+0

Me refiero específicamente al hecho de que la notación de puntos se usa en métodos * class *, no * métodos de instancia *. ¿Sigue siendo este comportamiento esperado? – Eric

+0

El hecho de que sea un método de clase no hace diferencia. Como Barry señaló, usar la notación de puntos es exactamente lo mismo que llamar a los métodos usando llaves cuadradas. –

10

En el "mal pero funciona" categoría, he estado conocido el uso de constructores de conveniencia con la notación de puntos de vez en cuando, como NSMutableArray *myArray = NSMutableArray.array

+15

Hombre, eso es totalmente malo. No sé si votar o votar negativamente por la maldad ... –

+0

Por supuesto, también puedes hacer "myView.setNeedsDisplay;" o cualquier otro mensaje que no tome ningún parámetro. – NSResponder

+3

Eres tan malvado, dejando que mis programadores se infecten con tus ideas. Mi jefe me suplicará de rodillas. Todas las personas que verán mi código y llorarán, porque yo también seré un tipo malo. – Binarian

0

Los Underscore más abusos biblioteca esta sintaxis mediante la devolución de los bloques de métodos de clase, lo que resulta en un código como éste:

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

Para entender cómo funciona esto, se ven en la definición de Underscore.array:

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

:

Underscore.array(array) 

... es equivalente a esto:

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