2012-02-09 13 views
12

No estoy seguro de cuánto uso a esta pregunta es, pero parece interesante para mí ...Sintaxis con puntos vs sintaxis del método con el captador =

pensé que el uso de la propiedad/sintetizar declaraciones fue equivalente a mí crear el captador /setter. Por lo tanto

// .h 
@property (nonatomic) BOOL on; 

// .m 
@synthesize on = _on; 

// In my mind synthesizes the following methods 

// - (BOOL)on; 
// - (void)setOn:(BOOL)on; 

Sin embargo si cambio de las declaraciones a la siguiente:

       v 
@property (nonatomic, getter=isOn) BOOL on; 

@synthesize on = _on; 

// In my mind synthesizes the following 

// - (BOOL)isOn; 
// - (void)setOn:(BOOL)on; 

A continuación, dado lo anterior puedo reemplazar el comprador, así que sé cuando se le llama:

- (BOOL)isOn; 
{ 
    NSLog(@"I was called"); 
    return _on; 
} 

Ahora llamando los siguientes en una instancia (myClass) resulta en:

NSLog(@"%d", [myClass isOn]); 

//=> 2012-02-09 22:18:04.818 Untitled[1569:707] I was called 
//=> 2012-02-09 22:18:04.820 Untitled[1569:707] 1 

NSLog(@"%d", myClass.isOn); 

//=> 2012-02-09 22:18:24.859 Untitled[1599:707] I was called 
//=> 2012-02-09 22:18:24.861 Untitled[1599:707] 1 

NSLog(@"%d", myClass.on);   // This is the one I didn't expect to work 

//=> 2012-02-09 22:18:55.568 Untitled[1629:707] I was called 
//=> 2012-02-09 22:18:55.570 Untitled[1629:707] 1 

siempre había asumido que si yo estaba usando una propiedad en este sentido, era perfectamente válida para utilizar el captador/definidor con la sintaxis con punto en la forma

myClass.isOn; 
myClass.on = on; 

De otra question se sugirió que cuando se utilizan puntos la sintaxis que debe utilizar el nombre de la propiedad de esta manera:

myClass.on // Correct 
myClass.isOn // Incorrect 

Aunque esto funciona parecer un poco menos lógico porque sé que no hay un método subyacente - (BOOL)on en su lugar se asigna a - (BOOL)isOn

Mis preguntas son (utilizando el último ejemplo)

  • Es esto un error o debería myClass.on realmente puede cambiar en silencio para llamar - (BOOL)isOn
  • hablando Semánticamente accedo estado de comportamiento no invocar por lo que es mi uso actual de sintaxis punto correcta? (Por ejemplo myClass.isOn)

actualización

Aunque nadie ha dicho explícitamente que he razonado que el uso de .isOn es mala forma porque independientemente del hecho de que bajo el capó se llama el mismo método, semánticamente isOn hace una pregunta, que es más comportamiento que estado.

Sin embargo, estoy todavía no está claro en donde el cableado "mágica" pasa que convierte las llamadas a myClass.on en [myClass isOn]


Actualización 2

Después de mirar los documentos poco más encontré esta sección sobre Declared Properties.Usando el siguiente código que puedo inspeccionar una clase propiedades:

id MyClass = objc_getClass("MyClass"); 
unsigned int outCount, i; 

objc_property_t *properties = class_copyPropertyList(MyClass, &outCount); 
for (i = 0; i < outCount; i++) { 
    objc_property_t property = properties[i]; 
    NSLog(@"Name: %s, attributes: %s\n", property_getName(property), property_getAttributes(property)); 
} 

//=> 2012-02-10 07:10:28.333 Untitled[934:707] Name: on, attributes: Tc,GisOn,V_on 

Así que tener los siguientes atributos:

  • Name = en
  • type = char (Tc)
  • captador = Ison (GISON)
  • variable = _on (V_on)

Con toda esta información disponible en tiempo de ejecución, deja la pregunta: ¿esta búsqueda se realiza en tiempo de ejecución o en tiempo de compilación como sugieren algunas respuestas?

Respuesta

4

Sin embargo, estoy todavía no está claro en donde el cableado "mágica" pasa que convierte las llamadas a myClass.on en [myClass Ison]

La lógica sin duda es la siguiente, al compilar un obj. nombrar en un contexto conseguir:

if(there is an accessible @property for name in scope) 
{ 
    if(there is a custom getter specified) 
     compile "[obj customGetter]" 
    else 
     compile "[obj name]" 
} 
else if (there is an an accessible instance method name in scope) 
    compile "[obj name]" 
else 
{ 
    compile "[obj name]" 
    warn obj may not respond to name 
} 

Hay otras maneras de un entorno de idioma/ejecución puede manejar nombres getter, pero dado que Obj-C pone la declaración en la cabecera (que es público) lo anterior es un buen adivinar dónde se realiza la lógica de obtención personalizada med: al compilar el sitio de llamadas.

+0

Obtengo lo que sucede conceptualmente. Estaba tratando de encontrar más documentación en lugar de solo mis observaciones.Por favor, consulte mi actualización que pregunta si esto se hace en tiempo de compilación o en tiempo de ejecución –

+0

@ Paul.s - OK Ejecuté una prueba simple (compilo ambas variantes y miro el ensamblador) y la respuesta es tiempo de compilación, al menos por el Clang actual compilador. Esto tiene sentido como sugerí antes: la información se coloca en el encabezado y no en la implementación. Realmente no puedo imaginar por qué se haría en tiempo de ejecución: la resolución sobre qué método invoca 'customGetter' todavía se hará en tiempo de ejecución. Para que la resolución del tiempo de ejecución del nombre de la propiedad en el nombre de usuario personalizado sea útil en el tiempo de ejecución, deberá querer permitir el cambio de esa asignación en el tiempo de ejecución. – CRD

2

bien en relación con la notación de punto, quisiera citar Aaron Hillegass (Cacao de programación para Mac OS X, 3ª Ed.):

"En general, creo que esto es una adición bastante tonto a la lengua ya que ya tenía una sintaxis para enviar mensajes ".

Cuando tiene una variable miembro activada, y su getter para esta variable se llama isOn, entonces .on y .isOn son dos tipos muy diferentes de cosas. Al usar el getter (y probablemente también un setter), se adherirá a la promesa de "ocultar información", mientras que al usar acceso directo a las variables miembro no lo hará. Cocoa no hará cumplir esas cosas ya que depende de las convenciones. Depende de usted decidir cuál es el mejor para usted. Teniendo en cuenta la convención, tendría que apegarse a los setters y getters, sin importar los nombres que les dé.

+1

Mi confusión es que '.on' y' .isOn' están pasando por '- (BOOL) isOn', por lo que técnicamente ambos se adhieren a la promesa de" ocultar información ". Sin embargo, todavía no hay 'acceso directo a las variables miembro'. Para obtener acceso directo, tendría que salir de mi camino para proporcionar un '@ public' ivar y luego usar la sintaxis' myClass -> _ on' –

+0

Ok Veo el punto. No tengo ningún comentario inmediato sobre esto hoy, pero hojearé los documentos mañana y veré si puedo encontrar algo. Hasta entonces (y mucho después, también), promociono no utilizar la sintaxis de punto en absoluto. –

3

Desde el experimento se puede inferir que la sintaxis con punto se interpreta de la siguiente manera:

  • existe una propiedad con ese nombre? Si es así, ¿tiene un nombre getter/setter especificado? si es así, llamemos a ese método.
  • de lo contrario, invente un nombre de método apropiado (directo si estamos obteniendo, setXX si estamos configurando) y tírelo al receptor.

Puede, por ejemplo, intentar usar .count contra una instancia de NSArray. Antes de que la abominación policial entre en tus puertas, es posible que tengas tiempo para ver si funciona.

Para responder realmente a su pregunta, en mi opinión la notación de puntos solo debe usarse para acceder a las propiedades, y en ese caso debe usar el nombre de la propiedad como declarado en la interfaz. Entonces .on para un UISwitch. No sé por qué el nombre getter no se da en la declaración de sintetizar en lugar de la declaración de propiedad, parece pertenecer a la implementación en lugar de a la interfaz.

+0

Me gusta que el punto acerca del nombre getter probablemente pertenezca a la implementación. Tal vez estoy mirando desde el ángulo equivocado, veo las propiedades como una forma abreviada que me permite no declarar explícitamente los métodos ivar y getter/setter. Por lo tanto, sin propiedades, declararía que los métodos '- (BOOL) isOn;' y '- (void) setOn: (BOOL) on;' y que no habría acceso a 'on '. Luego, agregando a eso, veo la sintaxis de punto expandiéndose a '- ' y '-set ', por lo que me confundí que 'myClass.on' parece expandirse a' [myClass isOn]; ' –

+0

En reflexión probablemente se requiera el nombre getter en el encabezado ya que es donde se define la interfaz pública, por lo que tiene sentido. –

+0

Sí, pensé eso después de ir a la cama. isOn ya se habría utilizado antes de que se introdujera la notación de propiedades/puntos para que los clientes de API puedan usar notación de puntos o llamadas a métodos, e isX es tradicional para un getter booleano, ya que hace que el código sea más legible. – jrturton

1

Las declaraciones de propiedades son meramente abreviadas para las declaraciones de métodos regulares. Por ejemplo:

@property int color; 
@property (getter=isOn) BOOL on; 

se convierte en estas declaraciones de métodos:

- (int)color; 
- (void)setColor:(int)value; 
- (BOOL)isOn; 
- (void)setOn:(BOOL)on; 

Puede llamar a estos métodos al igual que cualquier otro método:

[foo color]; 
[foo isOn]; 

Del mismo modo, la notación de puntos es la abreviatura meramente informal para llamar llanura viejos métodos.Por ejemplo:

x = @"Hello".length; 
x = foo.on; 
x = foo.isOn; 

convierte

x = [@"Hello" length]; 
x = [foo isOn]; 
x = [foo isOn]; 

Tenga en cuenta que a pesar de que las obras @"Hello".length NSString en realidad no declaran una propiedad denominada "longitud". De forma predeterminada, foo.bar siempre se expande a [foo bar]a menos quebar haya sido declarado como propiedad con un getter personalizado. Si bar resulta ser el nombre de un método válido, entonces funcionará sin error.

Del mismo modo, en su ejemplo foo.isOn funciona aunque realmente no declare una propiedad llamada "isOn". Más bien "isOn" es el nombre de un método que simplemente resulta ser el método getter para su propiedad "on".

Por lo tanto, aunque foo.isOn puede funcionar, se considera una forma incorrecta porque isOn no es realmente el nombre de la propiedad.

Lo que no puede hacer es esto:

x = [foo on]; // Error 

porque nunca se declare un método on.

Cuestiones relacionadas