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:
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
Operador de flecha en un objeto C (puntero)
Operador de punto / corchetes en un objeto Objective-C (puntero)
objc_msgSend
Operador de flecha en un objeto Objective-C (puntero)
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.