2009-06-22 9 views
7

¿Cuál es la diferencia entre una función C (estática o no) declarada dentro o fuera del bloque de implementación (@implementation ... @end) de una clase Objective-C?Obj-C: funciones C declaradas dentro o fuera del bloque @implementation, ¿cuál es la diferencia?

es especialmente cierto esto ?:

Si tiene que meter en el interior del objeto directamente, puede poner esta función dentro del bloque @implementation de su clase, y luego se puede acceder a las variables de instancia con el operador de flecha C Pero eso es un poco travieso, por lo tanto, para preservar tu Pureza de Esencia deberías estar usando llamadas de método en tu objeto. Fin del Sermón. Aquí está el mal:

@implementation OblateSphereoid 

void drawEggThunk (DrawingContext *context, Rect areaToDraw, void *userData) 
{ 
BWOblateSphereoid *dealie = (BWOblateSphereoid *)userData; 
dealie->_frognatz = [NSColor plaidColor]; 
// and more stuff. 
} // drawEggThunk 

... 
@end // OblateSphereoid 

¿Puedo acceder a las variables de instancia de mi clase dentro de las funciones (declaradas en la misma clase) de esta manera?

+0

Upvoted por una pregunta interesante (aunque tal vez una muy mala práctica) Solo por curiosidad, ¿solo puedes llamar a drawEggThunk desde dentro de tu clase? –

+0

no puedo, la función es una función de devolución de llamada llamada desde un subsistema C, como puede ver, yo uso * userData para pasar una referencia a uno mismo cuando se configuran las devoluciones de llamada. – jlpiedrahita

Respuesta

2

Si bien esto es legal, no entiendo por qué es necesario en el tipo de caso que ha descrito (y es una solución desagradable). ¿Por qué no puedes llamar a:

[dealie setFrognatz:[NSColor plaidColor]]; 

Si no suelen proporcionar una -setFrognatz:, simplemente que sea un método privado al declarar que en el interior del .m, pero por encima de esta definición de la función. (En realidad, no importa si es en el bloque @implementation en este caso.)

@interface BWOblateSphereoid() 
- (void)setFrognatz:(NSColor *)acolor 
@end 

@implementation OblateSphereoid 

void drawEggThunk (DrawingContext *context, Rect areaToDraw, void *userData) 
{ 
    BWOblateSphereoid *dealie = (BWOblateSphereoid *)userData; 
    [dealie setFrognatz:[NSColor plaidColor]]; 
    // and more stuff. 
} // drawEggThunk 

... 
@end // OblateSphereoid 

Hay unos pocos lugares donde -> notación puede ser útil. El más crítico es implementar -copyWithZone: donde puede ser absolutely required (un requisito que realmente enfatiza por qué odio cualquier código ObjC que se reproduzca con memoria bruta como NSCopyObject()). Pero recomiendo en contra de -> en la mayoría de los casos por las mismas razones que siempre recomiendo accesos. Incluso en el caso en que necesite pasar un ivar por referencia a una función C (otro uso común de ->), prefiero usar un temporal y luego asignarlo después.

considero el hecho de que no son Ivars @private por defecto a un error en ObjC .... puse @private en la parte superior de cada bloque @interface y han evitado varios errores desagradables de esa manera.

Por cierto, su solución tal como está escrita puede estar goteando un NSColor. Tal vez lo sea, tal vez no lo es, pero un accesorio sería cierto.

+0

El método "privado" es la respuesta para el problema subyacente (acceso ivars dentro de las funciones sin encapsulamiento de ruptura) :) pero ... ¿hay alguna diferencia entre las funciones dentro y fuera de @impementation? – jlpiedrahita

+0

por cierto, los ivars obj son por defecto @protected, este es el alcance perfecto: visible para la clase y las subclases, y oculto para el resto. – jlpiedrahita

+0

No hay diferencia entre @implementation interior y exterior. –

2

Esto funcionará bien si está dentro de su @implementación. Te recomiendo que lo hagas un método normal, pero funciona.

Si lo quita de su implementación, recibe esta advertencia: Advertencia: la variable de instancia '' está @protegida; esto será un error difícil en el futuro. Puede evitar este error, poniendo un @ pública antes de Ivar en la cabecera ... de este modo:

@public 
int myInt; 

Eso le permite acceder a las variables como un C (puntero) Struct donde aparece el objeto sin previo aviso.

Así que es factible, aunque no recomendado !!!

+0

Creo que esto también puede ser una mala práctica, pero no quiero exponer el ivar como público simplemente a favor de la encapsulación, pero mis funciones de devolución de llamada C deben ser capaces de ver los ivars de instancia. – jlpiedrahita

+0

Entonces deberías hacer lo que tienes que hacer ... no tienes que declarar todos tus iVars como públicos, puedes mezclarlos y combinarlos. – micmoo

Cuestiones relacionadas