2009-06-27 32 views

Respuesta

39

Las dos sintaxis sirven para diferentes propósitos.

una categoría denominada - @interface Foo (FooCategory) - generalmente se utiliza para:

(1) se extienden una clase existente mediante la adición de la funcionalidad. Ejemplo: NSAttributedString in Foundation se extiende por una categoría en AppKit que agrega API de formato de texto similar a RTF de AppKit.

(2) declara un conjunto de métodos que pueden ser implementados o no por un delegado. Ejemplo: varias clases declaran, pero no implementan, @interface NSObject (SetODelegateMethods).

El formulario (2) ha perdido vigencia ahora que @protocol se ha ampliado para admitir los métodos @optional en Objective-C 2.0.

Una extensión de clase - @interface Foo() - está diseñada para permitirle declarar una API privada adicional - SPI o Interfaz de Programación del Sistema - que se utiliza para implementar las entrañas de clase. Esto normalmente aparece en la parte superior del archivo .m. Cualquier método/propiedad declarada en la extensión de clase debe implementarse en @implementation, al igual que los métodos/propiedades que se encuentran en la interfaz @ pública.

Las extensiones de clase también se pueden usar para volver a declarar una propiedad @ de lectura pública como readwrite antes de @ sintetizar los accesadores.

Ejemplo:

foo.h

@interface Foo:NSObject 
@property(readonly, copy) NSString *bar; 
-(void) publicSaucing; 
@end 

Foo.m

@interface Foo() 
@property(readwrite, copy) NSString *bar; 
- (void) superSecretInternalSaucing; 
@end 

@implementation Foo 
@synthesize bar; 
.... must implement the two methods or compiler will warn .... 
@end 
+0

No la barra @synthesize; line significa que el compilador generará los dos métodos (getter y setter) para la barra? – Elliot

+2

Sí, pero solo el getter se declara en el encabezado público, el setter se declara en privado para su uso dentro de la clase misma. Esto no es C++, si quiere introspectar el tiempo de ejecución puede descubrir que el colocador está allí y llamarlo donde quiera, pero a menos que lo haga explícitamente obtendrá advertencias de compilación si casualmente intenta establecer la propiedad. –

+0

@Louis es correcto. La segunda propiedad anula esa "readonly" en la propiedad del archivo .h especificando "readwrite", así que eso es lo que realmente hace el compilador. Sin embargo, solo el getter es visible para las personas, incluido el archivo de encabezado, ya que cuando importan el archivo, solo verán la versión de "solo lectura" de la propiedad. –

2

Sí,

existen las siguientes diferencias.

1) El uso de categorías anónimas requiere implementar sus métodos en el bloque @implementation principal para la clase correspondiente; las categorías anónimas le permiten declarar una API adicional requerida para una clase en ubicaciones que no sean la clase primaria @interface block

2) Cuando se utiliza MyClass (privado), se debe tener en cuenta lo siguiente: el objeto/categoría nombrados pares debe ser único. Si declaras una categoría privada en tu propia clase, entonces no hay problemas. Sin embargo, las cosas son diferentes en las clases existentes. Por ejemplo, solo puede existir una categoría NSString (privada) en un espacio de nombres Objective-C determinado. Esto puede ocasionar problemas porque el espacio de nombres Objective-C se comparte entre el código del programa y todas las bibliotecas, marcos y complementos. Esto es especialmente importante para los programadores de Objective-C que escriben protectores de pantalla, paneles de preferencias y otros complementos porque su código se inyectará en el código de la aplicación o del marco que no controlan.

+0

¿Estás seguro de que es el caso de que las categorías tienen que ser identificado de forma única? Tengo entendido que siempre que los selectores sean únicos, no habrá conflictos. ¿El tiempo de ejecución es aún consciente de las categorías? (la referencia de tiempo de ejecución no los menciona) – rpetrich

+0

No es la categoría que debe tener un nombre exclusivo: es el objeto/categoría de par que debe ser.Intenta compilar dos categorías diferentes de NSString (Privado), incluso usando diferentes métodos en uno de tus proyectos y ve si esto funciona. –

+0

Hmm ... parece que el compilador/enlazador no permite categorías duplicadas en una clase, pero el tiempo de ejecución sí lo hace. Puede definir categorías NSDictionary (NSDictionary) o NSError (NSErrorPrivate) con un método + load y el compilador, el enlazador y el tiempo de ejecución se comportarán como se espera (aunque Foundation.framework implemente ambas categorías internamente). Si implementa una categoría que ha sido nombrada en un encabezado como NSString (NSStringExtensionMethods), el compilador emitirá advertencias, pero el enlazador y el tiempo de ejecución aún se comportan como se esperaba. Nada de esto es realmente útil en el mundo real aunque. – rpetrich

Cuestiones relacionadas