¿Cómo deben implementarse los miembros públicos y privados en el objective c?

Tuve algunas discusiones relacionadas con el uso de properties y variables de instancia en el trabajo, por lo tanto, me gustaría encontrar una respuesta wiki para eso. Ahora, sé que no hay un tipo de miembro privado real en el objective c, todo es bastante público. Sin embargo, estoy un poco preocupado por la forma en que debemos diseñar nuestras classs y también para cumplir con los principios de OOP. Me gustaría escuchar opiniones sobre estos tres enfoques de layout:

R. De acuerdo con varios post e incluso a un nuevo curso de desarrollo de iPhone de la Universidad de Stanford, siempre debe utilizar las properties donde pueda. Sin embargo, en mi humilde opinión, este enfoque frena los principios de layout de OOP porque en este caso, todos los miembros se hacen públicos. ¿Por qué tengo que publicar todas mis variables de instancia interna / local en el exterior? Además, hay una muy pequeña (pero aún) sobrecarga si utiliza sintetizadores sintetizados a través de properties, en lugar de usar ivar local directamente. He aquí un ejemplo:

//==== header file =====// @interface MyClass : NSObject @property (nonatomic, retain) NSString *publicMemberWithProperty; @property (nonatomic, retain) NSString *propertyForPrivateMember; @end 

B. Otro enfoque es declarar ivars en el file de encabezado (sin declarar properties relativas) para miembros privados, y en el mismo file de encabezado, para declarar properties puras (sin declarar ivars relativos) para miembros públicos. En tal caso, ivars se usaría directamente en la class. Este enfoque tiene sentido pero no utiliza todos los beneficios de las properties porque tenemos que liberar manualmente los valores anteriores antes de configurar los nuevos. He aquí un ejemplo:

 //==== header file =====// @interface MyClass : NSObject{ NSString *_privateMember; } @property (nonatomic, retain) NSString *publicMemberWithProperty; @end 

C. Declarar properties puras (sin declarar ivars relativos) para miembros públicos en el file de encabezado y declarar properties puras (sin declarar ivars relativos) para miembros privados en una interfaz privada en un file de implementación. Este enfoque IMHO es más claro que el primero, pero sigue habiendo la misma pregunta: ¿por qué tenemos que tener properties para miembros internos / locales? He aquí un ejemplo:

 //==== header file =====// @interface MyClass : NSObject @property (nonatomic, retain) NSString *publicMemberWithProperty; @end //==== implementation file =====// @interface MyClass() @property (nonatomic, retain) NSString *propertyForPrivateMember; @end 

Esta libertad de decisión me molesta un poco y me gustaría encontrar una confirmación de las respectivas fonts sobre cómo se deben hacer las cosas. Sin embargo, no pude encontrar declaraciones tan estrictas en los documentos de Apple sobre eso, así que por favor publica un enlace a Apple Docs si existe alguno, o a cualquier otra teoría que lo aclare.

Al usar extensiones de class puede tener properties privadas.

Una syntax de extensión de class es simple:

Dentro del file .m, que tiene la class, crea una categoría sin nombre:

.marido

 @interface OverlayViewController : UIViewController <VSClickWheelViewDelegate> - (IBAction)moreButtonClicked:(id)sender; - (IBAction)cancelButtonClicked:(id)sender; @end 

.metro

 #import "OverlayViewController.h" @interface OverlayViewController () @property(nonatomic) NSInteger amount; @property(retain,nonatomic)NSArray *colors; @end @implementation OverlayViewController @synthesize amount = amount_; @synthesize colors = colors_; //… @end 

Ahora tienes todos los aspectos de las properties para miembros privados, sin exponerlos a público. No debe haber una sobrecarga para las properties sintetizadas en getter / setters escritos, ya que el comstackdor creará más o less lo mismo en time de compilation.

Tenga en count que este código utiliza ivars sintetizados. No se necesita statement ivar en el encabezado.

Hay un bonito artículo de cocoawithlove sobre este enfoque.

También pregunta por qué usar properties para ivars privados. Hay varias buenas razones:

  • Las properties se ocupan de la propiedad y la gestión de la memory.
  • en cualquier momento en el futuro puede decidir, escribir un getter / setter personalizado. es decir, para volver a cargar una vista de tabla, una vez que NSArray ivar estaba recién configurado. Si utilizó properties por consiguiente, no se necesitan otros cambios.
  • Key Value Coding support properties.
  • Las properties de readonly públicas se pueden volver a declarar a las properties privadas de escritura de escritura.

editar
Desde LLVM 3 también es posible declarar ivars en extensiones de class

 @interface OverlayViewController (){ NSInteger amount; NSArray *colors; } @end 

o incluso en el bloque de implementación

 @implementation OverlayViewController{ NSInteger amount; NSArray *colors; } //… @end 

ver "WWDC2011: Sesión 322 – Avances del objective-C en profundidad" (~ 03: 00)

Realmente no hay una solución limpia, segura, cero, que sea soportada directamente por el lenguaje. Muchas personas se contentan con las características de visibilidad actuales, mientras que muchos sienten que les falta.

El time de ejecución podría (pero no) hacer esta distinción con ivars y methods. El mejor soporte de primera class sería la OMI. Hasta entonces, tenemos algunos modismos de abstracción:

Opción A

Es malo: todo es visible. No estoy de acuerdo con que sea un buen enfoque, y eso no es OOD (IMO). Si todo está visible, entonces tu class debería:

  • Apoye todos los casos sobre cómo el cliente puede usar su class (generalmente no razonable o indeseable)
  • o les proporciona un montón de reglas a través de la documentation (es probable que las actualizaciones de documentos pasen desapercibidas)
  • o los accesores no deben tener efectos secundarios (no OOD, y con frecuencia se traduce como 'no anular los accesores')

Opción B

Tiene las deficiencias de la Opción A ,, y al igual que la Opción A, a los miembros se puede acceder por key.

Opción C

Esto es un poco más seguro. Al igual que todos los demás, todavía puede usar acceso con key, y las subclasss pueden anular sus accesores (incluso sin saberlo).

Opción D

Un enfoque para esto es escribir su class como un contenedor a través de un tipo de implementación. Puede usar un tipo ObjC o un tipo C ++ para esto. Puede favorecer a C ++ donde la velocidad es importante (se mencionó en el OP).

Un enfoque simple a esto tomaría uno de los formularios:

 // inner ObjC type @class MONObjectImp; @interface MONObject : NSObject { @private MONObjectImp * imp; } @end // Inner C++ type - Variant A class MONObjectImp { ... }; @interface MONObject : NSObject { @private MONObjectImp imp; } @end // Inner C++ type - Variant B class MONObjectImp; @interface MONObject : NSObject { @private MON::t_auto_pointer<MONObjectImp> imp; } @end 

(Nota: desde que se escribió originalmente, se ha introducido la capacidad de declarar ivars en el bloque @implementation. Debería declarar sus types de C ++ allí si no es necesario para soportar cadenas de herramientas más antiguas o el OS X de 32 bits "frágil" ABI).

C ++ La variante A no es tan 'segura' como las demás, porque requiere la statement de la class visible para el cliente. En los demás casos, puede declarar y definir la class Imp en el file de implementación, ocultándolo de los clientes.

Entonces puedes exponer la interfaz que elijas. Por supuesto, los clientes aún pueden acceder a sus miembros si realmente quieren hacerlo a través del time de ejecución. Esto sería más fácil para ellos hacer con security con el tipo ObjC Imp: el time de ejecución de objc no admite la semántica de C ++ para los miembros, por lo que los clientes estarían pidiendo UB (IOW es todo POD para el time de ejecución).

El costo de time de ejecución para la implementación de ObjC es escribir un nuevo tipo, para crear una nueva instancia de Imp para cada instancia y una buena cantidad de duplicación de posts.

El tipo de C ++ no costará prácticamente nada, aparte de la asignación (Variante B).

Opción E

Otros enfoques a menudo disocian los ivars de las interfaces. Si bien esto es algo bueno , también es muy inusual para los types ObjC. Los types / layouts de ObjC a menudo mantienen relaciones estrechas con sus ivars y accesores, por lo que enfrentarás la resistencia de otros desarrolladores.

De manera similar a C ++, Objective C proporciona ámbitos públicos, privados y protegidos. También proporciona un scope de package que es similar al scope del package definido en Java. Las variables públicas de las classs pueden ser references en cualquier parte del progtwig. Las variables privadas solo se pueden hacer reference dentro de los posts de la class que lo declara. Se podría usar dentro de posts que pertenecen a CUALQUIER instancia de la misma class. El scope del package es similar al scope público dentro de la misma image, es decir, ejecutable o biblioteca. Según la documentation de Apple, en las architectures de 64 bits, las variables del scope del package definidas dentro de una image diferente deben ser tratadas como privadas. El scope variable está definido por @public, @private, @protected, @package modifiers. Estos modificadores se pueden usar de forma similar a C ++ o Java. Todas las variables enumeradas en una statement de scope pertenecen al mismo ámbito. Además, las variables pueden enumerarse en la misma línea donde se declara el scope.

  @interface VariableScope : NSObject { @public int iVar0; @protected int iVar1; @private int iVar2; @package int iVar3; @public int iVar01, iVar02; @protected int iVar11, iVar12; @private int iVar21, iVar22; @package int iVar31, iVar32; } @end 

Para get más información, use el enlace a continuación.

http://cocoacast.com/?q=node/100