Operador de punto (“.”) Y operador de flecha (“->”) en C vs. Objetivo-C

Estoy tratando de entender algunas de las diferencias en el uso y la syntax en C vs. Objective-C. En particular, quiero saber cómo (y por qué) el uso difiere para el operador de punto y el operador de flecha en C vs. Objective-C. Aquí hay un ejemplo simple.

Código C:

// declare a pointer to a Fraction struct Fraction *frac; ... // reference an 'instance' variable int n = (*frac).numerator; // these two expressions int n = frac->numerator; // are equivalent 

Código Objective-C:

 // declare a pointer to a Fraction Fraction *frac = [[Fraction alloc] init]; ... // reference an instance variable int n = frac.numerator; // why isn't this (*frac).numerator or frac->numerator?? 

Entonces, viendo cómo frac es el mismo en ambos progtwigs (es decir, es un puntero a un objeto Fraction o struct), ¿por qué están usando una syntax diferente al acceder a las propiedades? En particular, en C, se accede a la propiedad del numerator con frac->numerator , pero con Objective-C, se accede usando el operador de punto, con frac.numerator . Como frac es un puntero en ambos progtwigs, ¿por qué estas expresiones son diferentes? ¿Alguien puede ayudarme a aclarar esto?

frac es lo mismo en ambos progtwigs.

AC Fraction es una struct , que es un tipo base sin operadores sobrecargados y solo puede construirse y destruirse de manera predeterminada. Si define funciones o campos en la estructura, la forma de acceder a esas propiedades en C es con el operador de punto ( . ). Objective-C mantiene este operador cuando usa struct s. Para mayor comodidad, puede realizar una operación de eliminación de referencias y puntos utilizando el operador de flecha ( -> ) (las dos expresiones equivalentes que menciona). Objective-C también lo conserva cuando accede a struct s.

Una Fraction Objective-C en su ejemplo, sin embargo, es probablemente (se supondría) un puntero de al menos tipo id , que es simplemente un nombre de clase y un puntero a la instancia de esa clase bajo el capó. También es muy probable que sea una subclase de NSObject o NSProxy . Estas clases de Objective-C son especiales ya que tienen una capa completa de operaciones predefinidas sobre una estructura C (si realmente quieres profundizar en ella, puedes echar un vistazo a la Referencia de tiempo de ejecución de Objective-C ). También es importante tener en cuenta que una clase Objective-C siempre es un puntero .

Una de las operaciones más básicas es objc_msgSend . Cuando operamos en este tipo de objetos, el comstackdor de Objective-C interpreta un operador de punto ( . ) O la syntax de corchete ( [object method] ) como una objc_msgSend método objc_msgSend . Para obtener información más detallada sobre lo que realmente ocurre aquí, consulte esta serie de publicaciones de Bill Bumgarner, un ingeniero de Apple que supervisa el desarrollo del tiempo de ejecución de Obj-C.

El operador de flecha ( -> ) no se supone que se use en objetos Objective-C. Como dije, las instancias de la clase Objective-C son una estructura C con una capa adicional de comunicación agregada, pero esa capa de comunicación se pasa por alto cuando se usa la flecha. Por ejemplo, si abre Xcode y escribe [UIApplication sharedApplication]-> y luego muestra la lista de finalización del método, verá esto:

Una lista de ivars internos en un objeto Obj-C cuando se utiliza el operador de flecha

Aquí puede ver un grupo de campos normales que generalmente accedemos con syntax de corchetes cuadrados (como el [[UIApplication sharedApplication] delegate] ). Sin embargo, estos elementos particulares son los campos C que almacenan los valores de sus respectivas propiedades de Objective-C.

Entonces, puedes pensarlo de esta manera:

Operador de punto en un objeto C

  1. (en tiempo de ejecución) Valor de retorno del campo

Operador de flecha en un objeto C (puntero)

  1. Puntero de desreferencia
  2. Valor de retorno del campo

Operador de punto / corchetes en un objeto Objective-C (puntero)

  1. (en tiempo de comstackción) Reemplazar con llamada a objc_msgSend
  2. (en tiempo de ejecución) Buscar definición de clase Obj-C, lanzar excepción si algo salió mal
  3. Puntero de desreferencia
  4. Valor de retorno del campo

Operador de flecha en un objeto Objective-C (puntero)

  1. (en tiempo de ejecución) Puntero de desreferencia
  2. Valor de retorno del campo

Ahora definitivamente estoy simplificando demasiado aquí, pero para resumir: los operadores de flecha parecen hacer básicamente lo mismo en ambos casos, pero el operador de punto tiene un significado extra / diferente en Objective-C.

La notación de puntos es una elección de diseño. Como siempre tratamos con punteros para las instancias objc, supongo que los diseñadores querían algo familiar, que además no rompería los progtwigs existentes. Fue presentado en ObjC 2, hace solo unos años. Antes de eso, siempre tenías que usar corchetes para enviar mensajes.

Sin embargo, la notación de puntos hace la diferencia; no es un acceso directo, sino un mensaje .

Es decir:

 obj.property = val; // is the same as: [obj setProperty:val]; // and not: obj->property = val; val = obj.property; // is the same as: val = [obj property]; // and not: val = obj->property; 

Aún puede escribir obj->ivar para acceder a un puntero a los miembros del objeto (si está visible).

En tu primer ejemplo, Fraction es una estructura. En su segundo ejemplo, Fraction es una clase Objective-C (y en iOS probablemente sería una subclase de NSObject ).

C ++ no permite la sobrecarga del operator . . Por lo tanto, sin información adicional, puede deducir que la notación de puntos que está viendo es una construcción de lenguaje adicional integrada en Objective-C, en lugar de un operador definido o sobrecargado en C / C ++.

Como sucede, la notación de punto es simplemente una característica de diseño que los implementadores eligieron como una forma abreviada de acceso a la propiedad, totalmente equivalente al captador de corchetes:

 myObjCVar.prop == [myObjCVar prop]; 

El operador de puntos en los objetos es una syntax especial para acceder a las propiedades de los objetos. Llama a getter o setter de la propiedad detrás de las escenas. Entonces, por ejemplo, [@"hello" length] y @"hello".length son equivalentes *. Para todos los demás tipos, el punto es el mismo que el punto C, y la flecha siempre es la misma.

* Nota: El método de acceso no siempre tendrá el mismo nombre que la propiedad. Si se trata de una propiedad declarada y la statement designa un método getter o setter especial, se usará en su lugar.

La notación de punto y flecha son iguales en C que en Objective-C (superconjunto estricto de). Creo que la diferencia fundamental que debe distinguirse es la diferencia entre una estructura y un objeto Objective-C.

La notación de puntos utilizada para los objetos en Objective-C se usa para las propiedades que se introdujeron en Objective-C 2.0. Sin embargo, con las estructuras, la notación de punto y -> entre Objective-C y C son las mismas.