1

Possible Duplicate:
@class vs. #import

In the .h file you can add a class to be seen(dont know what the correct terminolgy for this is) by using

#import "SomeClass.h"

or instead use

@class SomeClass;

I've tried both methods and they both worked. Whats the difference? Should I be using one of the methods and not the other? What is best practice?

Community
  • 1
  • 1
  • Take a look at [this](http://stackoverflow.com/questions/322597/class-vs-import). It might answer your question. – Mihai Fratu Sep 11 '11 at 13:35
  • 1
    Found the same question here; hope this helps. http://stackoverflow.com/questions/322597/class-vs-import – Madhu Sep 11 '11 at 13:35

3 Answers3

11

#import includes the content of the header in the source. Thus, every declaration which is in the imported header is also imported.

@class only declares to the compiler that the given class exists, but does not import the header itself. It is called a forward declaration, as you only declares to the compiler that the class exists before defining it in details (telling which methods it implements and so on)

Consequences:

  • When using #import in your .m file, if the header is modified, it will trigger the recompilation of the .m file that #import it on next compilation. Instead, if you use @class, your .m does not depend on the header and if the header is modified, the .m file is not recompiled.
  • Using @class also avoid cross-imports, e.g. if the class A references class B and class B references class A, then you can't #import "A.h" in B.h and #import B.h in A.h in the same time (it would be an "import infinite loop")
  • Using @class only declare that a class exists and does not tell the compiler which methods the class responds to.

This is why usually the best practice is to forward-declare the class using @class A in the header (.h) files that references class A, just so that the compiler knows that "A" is a known class but doesn't need to know more, and #import "A.h" in the implementation (.m) file so that you can call methods on the objet of class A in your source file.

In addition to avoid import loops, this will also avoid to recompile files if they don't need to, and thus reduce your compile time.

The only exceptions are when the declaration of your class inherits another class, or when it declares that it conforms to a given @protocol (like delegate protocols and so on), because in this particular case, the compiler needs you to #import the whole definition of the parent class or @protocol (to know if your class correctly conforms to this given protocol).


MyClassA.h

// Tells the compiler that "MyClassB" is a class, that we will define later
@class MyClassB; // no need to #import the whole class, we don't need to know the whole definition at this stage

@interface MyClassA : NSObject {
    MyClassB* someB; // ok, the compiler knows that MyClassB is a class, that's all it needs to know so far
}
-(void)sayHello;
-(void)makeBTalk;
@end

MyClassB.h

@class MyClassA; // forward declaration here too
// anyway we couldn't #import "MyClassA.h" here AND #import "MyClassB.h" in MyClassA.h as it would create an unsolvable import loop for the compiler
@interface MyClassB : NSObject {
    MyClassA* someA; // ok, the compiler knows that MyClassA is a class, that's all it needs to know so far
}
-(void)talk;
-(void)makeABePolite;
@end

MyClassA.m

// import MyClassB so that we know the whole definition of MyClassB, including the methods it declares
#import "MyClassB.h" // thus we here know the "-talk" method of MyClassB and we are able to call it

@implementation MyClassA
-(void)sayHello { NSLog(@"A says Hello"); }
-(void)makeBTalk {
  [someB talk];
  // we can call the 'talk' method because we #imported the MyClassB header and knows this method exists
}
@end

MyClassB.m

// import MyClassA so that we know the methods it declares and can call them
#import "MyClassA.h"
@implementation MyClassB
-(void)talk { NSLog(@"B is talking"); }
-(void)makeABePolite {
  [someA sayHello];
  // we can call this because we #import MyClassA
}
@end

PS: Note that if this is a best practice, I know a lot of developers (including myself sometimes ^^) that #import the header it needs in their .h files, instead of only forward-declare it using @class... this is some bad habit — or because these developers doesn't know these subtleties — that you will unfortunately encounter in existing code anyway.

AliSoftware
  • 32,623
  • 6
  • 82
  • 77
0

Using @class is called forward declaration. Since usually you don't need to know the specifics of the class in the .h file, this is usually all you need.

Forward declaration prevents you getting into a situation where you import a particular .h file, which says to import another .h file, which says to import the original .h file again, and so on.

jrturton
  • 118,105
  • 32
  • 252
  • 268
0

The @class forward declaration allows you to have your interfaces behave like interfaces. Meaning: Declare your code.

But this doesn't mean that you can leave out the #import statement. You just moved the responsibility to the implementation to import and make use of it.

Basically it could be seen as an increase in performance as you're not importing any other headers inside your current header.

Important Note: This isn't the case when you're working with delegates. If you're making use of delegates you always have to have the proper #import statements in place so that the compiler knows which delegate methods are to be implemented by that class.

You might also want to have a look at the following SO question: @class vs. #import

Community
  • 1
  • 1
Faizan S.
  • 8,634
  • 8
  • 34
  • 63