2012-04-04 13 views
67

¿Cuál es la diferencia entre estas dos declaraciones de clase? No entiendo por qué @class se utiliza aquí. Gracias.Objective-C: ¿Directiva de clase antes de @interface?

@class TestClass; 

@interface TestClass: UIView { 
    UIImage *image1; 
    UIImage *image2; 
} 

y

@interface TestClass: UIView { 
    UIImage *image1; 
    UIImage *image2; 
} 

Respuesta

165

@class existe para romper las dependencias circulares. Supongamos que tiene las clases A y B.

@interface A:NSObject 
- (B*)calculateMyBNess; 
@end 

@interface B:NSObject 
- (A*)calculateMyANess; 
@end 

Pollo; conoce a Egg. Esto nunca puede compilarse porque la interfaz de A depende de que B se defina y viceversa.

Por lo tanto, se puede corregir mediante el uso de @class:

@class B; 
@interface A:NSObject 
- (B*)calculateMyBNess; 
@end 

@interface B:NSObject 
- (A*)calculateMyANess; 
@end 

@class dice efectivamente el compilador que existe en algún lugar y, por lo tanto, los punteros declarados a constatar la práctica de dicha clase son perfectamente válida dicha clase. Sin embargo, no puede invocar un método en una referencia de instancia cuyo tipo solo está definido como @class porque no hay metadatos adicionales disponibles para el compilador (no recuerdo si revierte el sitio de la llamada para que se evalúe como una llamada a través de id o no).

En su ejemplo, el @class es inofensivo, pero completamente innecesario.

+17

Ojalá pudiera dar otro +1 solo por 'chicken, meet egg' – lukya

+4

BTW, vuelve a la evaluación 'id'. – jheld

+0

¿Hay motivos particulares por los que algunas personas colocan '@ class' en su archivo .h y luego importan los archivos de encabezado necesarios en su archivo .m, y otros pueden simplemente importar el archivo .h en el archivo de encabezado de las clases actuales? Solo curiosidad, gracias. @bbum –

15
@class TestClass; 

Esto simplemente declara "clase TestClass se definirá".

En este caso (el que pegaste) esto no tiene ningún efecto de ningún tipo, por lo que estos son los mismos.

Sin embargo, en caso de que vaya a definir un protocolo que usaría su nombre de clase (como tipo de parámetros pasados ​​a delegar, por ejemplo), deberá declarar @class TestClass antes de la definición del protocolo, ya que su clase todavía no está definido.

En general, si es necesario mencionar el nombre de la clase antes de que se hizo la definición de clase, tendrá que emitir @class declaración primera

+0

he visto esta implementación es la más importante antes de los protocolos. ¡gracias por compartir! – SleepsOnNewspapers

6

De acuerdo con la respuesta de Matt no hay absolutamente ningún punto de la declaración @class en el código. @class forward define una clase para que luego el compilador sepa a qué tipo de unidad general se refiere. Dado que Objective-C es casi sin tipo en el tiempo de ejecución, eso es a menudo todo lo que el compilador realmente necesita saber, solo lo suficiente para distinguir la cosa de un valor atómico de C.

Voy a tomar una puñalada en la oscuridad y digo que debido a que las variables de instancia están declaradas en el @interface, estás viendo un código anterior. Debido a que es código antiguo, el @class probablemente solía estar en otro lugar (por ejemplo, había un protocolo de delegado declarado en el medio) y acaba simplemente varado inofensivamente.

1

@class es bastante útil cuando necesita definir un protocolo para un objeto que generalmente interactuará con el objeto cuya interfaz también está definiendo. Usando @class, puede mantener la definición del protocolo en el encabezado de su clase. Este patrón de delegación se usa a menudo en Objective-C, y a menudo es preferible a definir tanto "MyClass.h" como "MyClassDelegate.h".Esto puede causar algunos problemas de importación confusas

@class MyClass; 

@protocol MyClassDelegate<NSObject> 

- (void)myClassDidSomething:(MyClass *)myClass 
- (void)myClass:(MyClass *)myClass didSomethingWithResponse:(NSObject *)reponse 
- (BOOL)shouldMyClassDoSomething:(MyClass *)myClass; 
- (BOOL)shouldMyClass:(MyClass *)myClass doSomethingWithInput:(NSObject *)input 

@end 

@interface MyClass : NSObject 

@property (nonatomic, assign) id<MyClassDelegate> delegate; 

- (void)doSomething; 
- (void)doSomethingWithInput:(NSObject *)input 

@end 

Entonces, cuando se utiliza la clase, puede tanto crear instancias de la clase, así como implementar el protocolo con una sola declaración de importación

#import "MyClass.h" 

@interface MyOtherClass()<MyClassDelegate> 

@property (nonatomic, strong) MyClass *myClass; 

@end 

@implementation MyOtherClass 

#pragma mark - MyClassDelegate Protocol Methods 

- (void)myClassDidSomething:(MyClass *)myClass { 

    NSLog(@"My Class Did Something!") 

} 

- (void)myClassDidSomethingWithResponse:(NSObject *)response { 

    NSLog(@"My Class Did Something With %@", response); 

} 

- (BOOL)shouldMyClassDoSomething { 

    return YES; 

- (BOOL)shouldMyClassDoSomethingWithInput:(NSObject *)input { 

    if ([input isEqual:@YES]) { 

     return YES; 

    } 

    return NO; 

} 


- (void)doSomething { 

    self.myClass = [[MyClass alloc] init]; 
    self.myClass.delegate = self; 
    [self.myClass doSomething]; 
    [self.myClass doSomethingWithInput:@0]; 

} 
Cuestiones relacionadas