Pregunta 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 sintaxis 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 programas (es decir, es un puntero a un objeto Fraction o struct), ¿por qué utilizan una sintaxis diferente al acceder a las propiedades? En particular, en C, el numerator se accede a la propiedad con frac->numerator, pero con Objective-C, se accede usando el operador punto, con frac.numerator. Ya que frac es un puntero en ambos programas, ¿por qué son estas expresiones diferentes? ¿Alguien puede ayudarme a aclarar esto?


57
2018-01-31 00:12


origen


Respuestas:


frac en realidad no es lo mismo en ambos programas.

A C Fraction es un 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 punto (.) operador. Objective-C mantiene este operador cuando usa structs. Para mayor comodidad, puede realizar una operación de eliminación de referencias y puntos utilizando la flecha (->) operador (las dos expresiones equivalentes que mencionas). Objective-C también lo conserva al acceder structs.

Un objetivo-C Fraction en su ejemplo, sin embargo, es probable (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 además de solo una C struct (si realmente quieres profundizar en él, entonces puedes echarle un vistazo al Referencia de tiempo de ejecución de Objective-C) También es importante tener en cuenta que una clase Objective-C es siempre un puntero.

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

La flecha (->) no se supone que el operador 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 mostrar la lista de finalización del método, verá esto:

A list of internal ivars on an Obj-C object when using the arrow operator

Aquí puede ver un montón de campos normales que generalmente accedemos con sintaxis de corchetes cuadrados (como [[UIApplication sharedApplication] delegate]) Estos artículos en particular, sin embargo, son Ccampos 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 compilació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.


72
2018-01-31 01:09



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 programas 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 puedes escribir obj->ivar para acceder a un puntero a los miembros del objeto (si está visible).


9
2018-01-31 00:18



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

C ++ no permite sobrecarga de 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];

6
2018-01-31 00:18



El operador de puntos en los objetos es una sintaxis especial para acceder a las propiedades de los objetos. Llama a getter o setter de la propiedad detrás de las escenas. Así 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 declaración designa un método getter o setter especial, se usará en su lugar.


2
2018-01-31 00:18



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.


1
2018-01-31 00:22