objective-c syntax coding-style

objective c - Notación de puntos vs. notación de mensajes para propiedades declaradas



objective-c syntax (19)

Ahora tenemos la notación "punto" para las propiedades. He visto varios forths sobre los méritos de la notación de puntos frente a la notación de mensajes. Para mantener las respuestas sin contaminar, no voy a responder de ninguna manera en la pregunta.

¿Cuál es su pensamiento acerca de la notación de puntos frente a la notación de mensajes para el acceso a la propiedad?

Por favor, trate de mantenerlo enfocado en Objective-C - mi único prejuicio que propongo es que Objective-C es Objective-C, por lo que su preferencia de que sea como Java o JavaScript no es válida.

Los comentarios válidos tienen que ver con problemas técnicos (orden de operación, precedencia de lanzamiento, rendimiento, etc.), claridad (estructura vs. naturaleza del objeto, tanto pro como con!), Concisión, etc.

Tenga en cuenta que soy de la escuela de calidad rigurosa y legibilidad en código habiendo trabajado en grandes proyectos donde la convención y la calidad del código es primordial (el paradigma de escritura una vez leído mil veces).


Creo que podría cambiar a la mensajería en lugar de la notación de puntos porque en mi cabeza object.instanceVar es solo instanceVar que pertenece al objeto , para mí no se parece en nada a una llamada a método , que sí lo es, así que podría haber cosas que vayan pasando en su acceso y si usa instanceVar o self.instanceVar podría tener una diferencia mucho mayor que simplemente implícita vs. explícita. Solo mi 2 ¢.


De acuerdo, la notación de puntos en Objective-C parece extraña, de hecho. Pero aún no puedo hacer lo siguiente sin él:

int width = self.frame.size.width;

Funciona bien, pero:

int height = [[[self frame] size] height];

Me da "No se puede convertir a un tipo de puntero". Sin embargo, me gustaría mantener mi código en constante coherencia con la notación de mensajes.


En mi opinión, la sintaxis de puntos hace que Objective-C sea menos Smalltalk-esque. Puede hacer que el código parezca más simple, pero agrega ambigüedad. ¿Es una struct , union u objeto?


En su mayoría me crié en la edad de Objective-C 2.0, y prefiero la notación de puntos. Para mí, permite la simplificación del código, en lugar de tener paréntesis adicionales, solo puedo usar un punto.

También me gusta la sintaxis de puntos porque me hace sentir realmente como si estuviera accediendo a una propiedad del objeto, en lugar de solo enviarle un mensaje (por supuesto, la sintaxis de puntos realmente se traduce en el envío de mensajes, pero por el bien de las apariencias , el punto se siente diferente). En lugar de "llamar a un getter" por la sintaxis antigua, realmente parece que estoy obteniendo algo útil directamente del objeto.

Parte del debate en torno a esto se refiere a "¡Pero ya tenemos sintaxis de puntos, y es para structs !". Y eso es verdad Pero (y de nuevo, esto es solo psicológico) básicamente me parece lo mismo. Acceder a una propiedad de un objeto usando sintaxis de punto se siente igual que acceder a un miembro de una estructura, que es más o menos el efecto deseado (en mi opinión).

**** Edit: Como bbum señaló, también puedes usar sintaxis de puntos para llamar a cualquier método en un objeto (no estaba al tanto de esto). Así que diré que mi opinión sobre sintaxis de puntos es solo para tratar con las propiedades de un objeto, no el envío de mensajes todos los días **


Esta es una gran pregunta y veo muchas respuestas diferentes a esto. Aunque muchos han abordado los temas, trataré de responder a esto desde un ángulo diferente (algunos podrían haberlo hecho implícitamente):

Si utilizamos la notación ''punto'', la resolución del objetivo para el método se realiza en tiempo de compilación. Si usamos el mensaje que pasa, la resolución del objetivo se difiere a la ejecución en tiempo de ejecución. Si los objetivos se resuelven en tiempo de compilación, la ejecución es más rápida, ya que la resolución de los objetivos en el tiempo de ejecución incluye algunos gastos generales. (No es que la diferencia de tiempo importe mucho). Como ya hemos definido la propiedad en la interfaz del objeto, no tiene sentido diferir la resolución del objetivo para una propiedad en tiempo de ejecución y, por lo tanto, la notación de puntos es la notación que debemos usar para acceder a la propiedad.


Honestamente, creo que todo se reduce a una cuestión de estilo. Personalmente, estoy en contra de la sintaxis de puntos (especialmente después de descubrir que puedes usarla para llamadas a métodos y no solo para leer / escribir variables). Sin embargo, si va a utilizarlo, recomendaría encarecidamente no usarlo para nada más que para acceder y cambiar variables.


La notación de punto Objective-C es un azúcar sintáctico que se traduce al paso normal de mensajes, por lo que bajo el capó no cambia nada y no hace ninguna diferencia en el tiempo de ejecución. La notación de puntos no es más rápida que el envío de mensajes.

Después de que esto necesitó un pequeño preámbulo, he aquí los pros y los contras que he visto:

Dot pros y contras de notación

  • pros

    • legibilidad: la notación de puntos es más fácil de leer que los paréntesis anidados que pasan los masajes
    • Simplifica la interacción con los atributos y las propiedades: al usar la notación de puntos para las propiedades y la notación de mensajes para los métodos, puede lograr la separación del estado y el comportamiento en el nivel de síntesis
    • Es posible usar el operador de asignación de compuesto (1) .
    • usando la @property y la notación de puntos, el compilador hace mucho trabajo por usted, puede generar código para una buena administración de la memoria al obtener y establecer la propiedad; esta es la razón por la cual las guías oficiales de Apple sugieren la notación de puntos.
  • contras

    • La notación de @property está permitida solo para acceder a una @property declarada
    • Dado que Objective-C es una capa superior al estándar C (extensión del lenguaje), la notación de puntos realmente no deja en claro si la entidad a la que se accede es un objeto o una estructura. A menudo, parece que estás accediendo a las propiedades de una estructura.
    • llamando a un método con la notación de puntos que pierde los parámetros nombrados ventajas de legibilidad
    • cuando la notación mixta de mensajes y la notación de puntos parece que está codificando en dos idiomas diferentes

Ejemplos de código:

(1) Ejemplo de código de uso del operador compuesto:

//Use of compound operator on a property of an object anObject.var += 1; //This is not possible with standard message notation [anObject setVar:[anObject var] + 1];


La notación de puntos intenta hacer que los mensajes se vean como accesos a un miembro de una estructura, que no son. Podría funcionar bien en algunos casos. Pero pronto alguien presentará algo como esto:

NSView *myView = ...; myView.frame.size.width = newWidth;

Se ve bien. Pero no es. Es lo mismo que

[myView frame].size.width = newWidth;

que no funciona El compilador acepta el primero, pero legítimamente no el segundo. E incluso si emitió un error o advertencia por primera vez, esto es confuso.


Llámame flojo pero si tuviera que escribir un solo ''.'' frente a dos [] cada vez para obtener los mismos resultados, preferiría una sola. Odio los lenguajes detallados. El () en lisp me volvió loco. El lenguaje elegante como las matemáticas son concisos y efectivos, todos los demás se quedan cortos.


Lo uso para las propiedades porque

for ( Person *person in group.people){ ... }

es un poco más fácil de leer que

for ( Person *person in [group people]){ ... }

en el segundo caso, la legibilidad se interrumpe al poner su cerebro en el modo de envío de mensajes, mientras que en el primer caso está claro que está accediendo a las personas propiedad del objeto de grupo.

También lo usaré cuando modifique una colección, por ejemplo:

[group.people addObject:another_person];

es un poco más legible que

[[group people] addObject:another_person];

El énfasis en este caso debe estar en la acción de agregar un objeto a la matriz en lugar de encadenar dos mensajes.


Muchas personas parecen estar mezclando ''propiedades'' con ''variables de instancia''. El punto de las propiedades es hacer posible modificar el objeto sin tener que conocer sus partes internas, creo. La variable de instancia es, la mayoría de las veces, la ''implementación'' de una propiedad (que a su vez es la ''interfaz''), pero no siempre: a veces una propiedad no corresponde a un ivar, y en su lugar, calcula un valor de retorno '' sobre la marcha''.

Es por eso que creo que la idea de que "la sintaxis punto te engaña para que pienses que estás accediendo a la variable, por lo que es confusa" es incorrecta. Punto o corchete, no debe hacer suposiciones sobre las partes internas: es una Propiedad, no un ivar.


No use puntos para el comportamiento. Use dot para acceder o establecer atributos como cosas, generalmente atributos declarados como propiedades.

x = foo.name; // good foo.age = 42; // good y = x.retain; // bad k.release; // compiler should warn, but some don''t. Oops. v.lockFocusIfCanDraw; /// ooh... no. bad bad bad

Para gente nueva en Objective-C, recomendaría no usar el punto para nada, sino cosas declaradas como @property. Una vez que tenga una idea del idioma, haga lo que le parezca correcto.

Por ejemplo, encuentro el siguiente perfectamente natural:

k = anArray.count; for (NSView *v in myView.subviews) { ... };

Puedes esperar que el analizador estático clang aumente la capacidad de permitirte comprobar que el punto se usa solo para ciertos patrones o no para ciertos otros patrones.


Permítanme comenzar diciendo que comencé a programar en Visual / Real Basic, luego pasé a Java, así que estoy bastante acostumbrado a la sintaxis de puntos. Sin embargo, cuando finalmente me mudé a Objective-C y me acostumbré a los corchetes, luego vi la introducción de Objective-C 2.0 y su sintaxis de punto, me di cuenta de que realmente no me gusta. (para otros idiomas está bien, porque así es como funcionan).

Tengo tres beefs principales con sintaxis de punto en Objective-C:

Carne de vaca n. ° 1: no deja claro por qué podría estar recibiendo errores. Por ejemplo, si tengo la línea:

something.frame.origin.x = 42;

Entonces obtendré un error de compilación, porque something es un objeto, y no puedes usar las estructuras de un objeto como el valor l de una expresión. Sin embargo, si tengo:

something.frame.origin.x = 42;

Entonces compila muy bien, porque something es una estructura en sí que tiene un miembro de NSRect, y puedo usarlo como valor l.

Si adoptara este código, necesitaría pasar algún tiempo tratando de descubrir qué es something . ¿Es una estructura? ¿Es un objeto? Sin embargo, cuando usamos la sintaxis del corchete, es mucho más claro:

[something setFrame:newFrame];

En este caso, no hay absolutamente ninguna ambigüedad si something es un objeto o no. La introducción de la ambigüedad es mi carne de vacuno # 1.

Beef # 2: en C, la sintaxis de punto se usa para acceder a los miembros de las estructuras, no a los métodos de llamada. Los programadores pueden anular los setFoo: y foo de un objeto, y aún acceder a ellos a través de something.foo . En mi opinión, cuando veo expresiones que usan sintaxis de punto, espero que sean una simple asignación en un ivar. Este no es siempre el caso. Considere un objeto controlador que media una matriz y una tabla vista. Si llamo a myController.contentArray = newArray; , Esperaría que reemplazara la matriz anterior con la nueva matriz. Sin embargo, el programador original podría haber reemplazado a setContentArray: no solo para establecer la matriz, sino también para volver a cargar la tabla vista. Desde la línea, no hay indicios de ese comportamiento. Si [myController setContentArray:newArray]; que ver [myController setContentArray:newArray]; , entonces pensaría "Aha, un método. Tengo que ir a ver la definición de este método solo para asegurarme de que sé lo que está haciendo".

Así que creo que mi resumen de Beef # 2 es que puedes anular el significado de la sintaxis de punto con código personalizado.

Ternera # 3: Creo que se ve mal. Como programador de Objective-C, estoy totalmente acostumbrado a la sintaxis de corchetes, por lo que estoy leyendo a lo largo y veo líneas y líneas de bellos corchetes y luego de repente se rompe con foo.name = newName; foo.size = newSize; foo.name = newName; foo.size = newSize; etc. me distrae un poco. Me doy cuenta de que algunas cosas requieren sintaxis de punto (estructuras C), pero esa es la única vez que las uso.

Por supuesto, si está escribiendo código para usted, use lo que sea que le resulte cómodo. Pero si está escribiendo un código que está pensando en una fuente abierta, o si está escribiendo algo que no espera mantener para siempre, entonces le recomiendo usar la sintaxis del paréntesis. Esto es, por supuesto, solo mi opinión.

Sintaxis reciente de blog contra punto: forths

Refutación a la publicación anterior: http://eschatologist.net/blog/?p=226 (con el artículo original a favor de sintaxis punto: http://eschatologist.net/blog/?p=160 )


Personalmente, no uso ninguna notación de puntos en el código. Solo lo uso en la expresión de enlace CoreData KVC cuando sea necesario.

La razón para no usarlos en código para mí es que la notación de puntos oculta la semántica del colocador. Establecer una propiedad en notación de puntos siempre se parece a la asignación independientemente de la semántica del setter (asignar / retener / copiar). El uso de la notación de mensaje hace que sea visible que el objeto receptor tiene control sobre lo que sucede en el colocador y subraya el hecho de que esos efectos deben ser considerados.

Todavía estoy considerando si puedo usar la notación de puntos al recuperar el valor de una propiedad declarada o compatible con KVC porque es cierto que es un poco más compacta y legible, y no hay semántica oculta. En este momento me estoy quedando con la notación de mensajes en aras de la coherencia.


Soy un nuevo desarrollador de Cocoa / Objective-C, y mi opinión es la siguiente:

Me apego a la notación de mensajes, aunque comencé con Obj-C 2.0, y aunque la notación de puntos es una sensación más familiar (Java es mi primer idioma) Mi razón para esto es bastante simple: todavía no entiendo exactamente por qué agregaron la notación de punto al idioma. Para mí, parece una adición innecesaria e "impura". Aunque si alguien puede explicar cómo beneficia el idioma, estaría feliz de escucharlo.

Sin embargo, considero que esta es una elección estilística, y no creo que haya una forma correcta o incorrecta, siempre y cuando sea consistente y legible , al igual que con cualquier otra opción estilística (como poner tu llave de apertura en la misma línea que el encabezado del método o la siguiente línea).


Una de las principales ventajas de la programación orientada a objetos es que no hay acceso directo al estado interno de los objetos.

La sintaxis de punto me parece un intento de hacer que se vea y se sienta como si se estuviera accediendo directamente al estado. Pero en verdad, es solo azúcar sintáctico sobre los comportamientos -foo y -setFoo :. Yo prefiero llamar a una espada una espada. La sintaxis de puntos ayuda a la legibilidad en la medida en que el código es más sucinto, pero no ayuda a la comprensión porque al no tener en cuenta que realmente está llamando -foo y -setFoo: podría significar problemas.

Los accesadores sintetizados me parecen un intento de facilitar la escritura de objetos a los que se accede directamente al estado. Mi creencia es que esto fomenta exactamente el tipo de diseño de programa que la programación orientada a objetos fue creada para evitar.

A fin de cuentas, prefiero la sintaxis de puntos y las propiedades nunca se han introducido. Solía ​​ser capaz de decirle a la gente que ObjC tiene algunas extensiones limpias para C para hacerlo más parecido a Smalltalk, y no creo que eso sea cierto más.


Usar el estilo de un idioma, consistente con el idioma en sí, es el mejor consejo aquí. Sin embargo, este no es un caso de escribir código funcional en un sistema OO (o viceversa) y la notación punto es parte de la sintaxis en Objective-C 2.0.

Cualquier sistema puede ser mal utilizado. La existencia del preprocesador en todos los lenguajes basados ​​en C es suficiente para hacer cosas bastante extrañas; solo mira el Concurso C Ofuscado si necesitas ver exactamente qué tan extraño puede ser. ¿Eso significa que el preprocesador es automáticamente malo y que nunca deberías usarlo?

El uso de la sintaxis de punto para acceder a las propiedades, que se han definido como tales en la interfaz, está abierto al abuso. La existencia de abuso en potentia no debe ser necesariamente el argumento en contra.

El acceso a la propiedad puede tener efectos secundarios. Esto es ortogonal a la sintaxis utilizada para adquirir esa propiedad. CoreData, delegación, propiedades dinámicas (primero + último = completo) necesariamente harán algún trabajo bajo las cubiertas. Pero eso sería confundir ''variables de instancia'' con ''propiedades'' de un objeto. No hay ninguna razón por la cual las propiedades necesariamente deban almacenarse tal como están, especialmente si se pueden calcular (por ejemplo, la longitud de un String, por ejemplo). Entonces, ya sea que use foo.fullName o [foo fullName], todavía habrá una evaluación dinámica.

Por último, el comportamiento de la propiedad (cuando se usa como un valor l ) se define por el objeto mismo, como si se toma una copia o si se retiene. Esto hace que sea más fácil cambiar el comportamiento más adelante, en la propia definición de propiedad, en lugar de tener que volver a implementar los métodos. Eso se suma a la flexibilidad del enfoque, con la probabilidad resultante de que se produzcan menos errores (de implementación). Todavía existe la posibilidad de elegir el método incorrecto (es decir, copiar en lugar de retener), pero eso es un problema arquitectónico en lugar de la implementación.

En última instancia, se reduce a la pregunta "¿se ve como una estructura?". Este es probablemente el principal diferenciador en los debates hasta el momento; si tiene una estructura, funciona de manera diferente que si tiene un objeto. Pero eso siempre ha sido cierto; no puede enviar un mensaje a struct, y necesita saber si está basado en la pila o en la referencia / malloc. Ya hay modelos mentales que difieren en términos de uso ([[CGRect alloc] init] o struct CGRect?). Nunca se han unificado en términos de comportamiento; necesitas saber con qué estás tratando en cada caso. Es muy poco probable que agregar denotación de propiedad para objetos confunda a cualquier programador que sepa cuáles son sus tipos de datos; y si no lo hacen, tienen problemas mayores.

En cuanto a consistencia; (Objetivo-) C es inconsistente dentro de sí mismo. = se usa tanto para asignación como para igualdad, según la posición léxica en el código fuente. * se usa para punteros y multiplicación. Los BOOL son caracteres, no bytes (u otro valor entero), a pesar de que SÍ y NO son 1 y 0 respectivamente. La consistencia o pureza no es para lo que el lenguaje fue diseñado; se trataba de hacer las cosas.

Entonces, si no quieres usarlo, no lo uses. Hazlo de una manera diferente. Si quieres usarlo, y lo entiendes, está bien si lo usas. Otros lenguajes tratan los conceptos de estructuras de datos genéricos (mapas / estructuras) y tipos de objetos (con propiedades), a menudo usando la misma sintaxis para ambos a pesar del hecho de que uno es simplemente una estructura de datos y el otro es un objeto rico. Los programadores en Objective-C deberían tener una capacidad equivalente para poder tratar con todos los estilos de programación, incluso si no es el preferido.


Yo prefiero la sintaxis de mensajería ... pero solo porque eso es lo que aprendí. Teniendo en cuenta muchas de mis clases y lo que no están en el estilo Objective-C 1.0, no me gustaría mezclarlos. No tengo ninguna razón real además de "a lo que estoy acostumbrado" por no usar la sintaxis de punto ... EXCEPTO por esto, esto me vuelve loco

[myInstance.methodThatReturnsAnObject sendAMessageToIt]

No sé por qué, pero realmente me enfurece, sin una buena razón. Solo creo que eso

[[myInstance methodThatReturnsAnObject] sendAMessageToIt]

es más legible ¡Pero a cada cual lo suyo!


Usa notación de puntos (siempre que puedas)

En métodos de instancia que devuelven algún valor

No use notación de puntos

En los métodos de instancia que devuelven void, on init methods o en Class method.

Y mi excepción favorita personal

NSMutableArray * array = @[].mutableCopy;