@class vs #import


#1

I’m a bit confused about when exactly I should use @class vs #import.

The chapter says this for @class:
@class Asset; line tells the compiler “There is a class called Asset. Don’t panic when you see it in this file. That’s all you need to know for now.”

And this for #import:
To process the Employee.m file, the compiler needs to know a lot about the Asset class. Thus, you imported Asset.h instead of using @class.

Is there a reliable criteria that I can use to judge between “that’s all you need to know for now” and “a lot”?


#2

You use the @class directive to make a forward declaration of a type. All you need is a forward declaration, when the compiler does not need to know much about a type. For example, when you only declare a pointer to that type (this is normally what you would do in a header file.)

However, you must #import if the compiler needs to know much about a type. For example, when you create an instance of that type, or when you invoke methods on instances of that type, etc (this is normally what you would do in an implementation file.)


#3

I still don’t get it. Employee.h does the forward referencing of class “Asset” but then Employee.m imports the file “Assets.h” along with the file “Employee.h”. Why can we not just import “Assets.h” into the “Employee.h” file? Then the @Class referencing would be unnecessary.

You use the @class directive to make a forward declaration of a type. All you need is a forward declaration, when the compiler does not need to know much about a type. For example, when you only declare a pointer to that type (this is normally what you would do in a header file.)

However, you must #import if the compiler needs to know much about a type. For example, when you create an instance of that type, or when you invoke methods on instances of that type, etc (this is normally what you would do in an implementation file.)[/quote]


#4

Depending on the circumstances, including a header file from another header file can increase the burden on the compiler (because it may have to open and read in the corresponding header file whenever it encounters an import statement.)

For the examples in the book, this is not an issue.

However, it can become a major issue if one header file (say Foo.h) unnecessarily includes another header file (say Bar.h) which is a few tons in weight, and Foo.h gets included by dozens of other header files.

So whenever possible, we try to avoid including header files from other header files and include them only in the implementation files (because an implementation file is read by the compiler only once during a build and the same header file may be read more than once.)


#5

The existence of @class was also partially to be a solution to the “Foo.h imports Bar.h which imports Foo.h which imports Bar.h” infinite loop problem.

All #import does is say to the preprocessor (which runs before the compiler), “hey, copy and paste the stuff in this .h file right here”.

All @class does is promise the compiler, “Hey, take my word for it, this class exists. So even though I haven’t imported a header for it, don’t barf when I try to declare a method that takes or returns an instance of this class.”

So, especially when you have two headers that import each other, move the header imports to the .m files and use @class in the headers.

But since @class merely states, “hey, this class exists” but doesn’t actually tell the compiler anything /about/ the class, you still have to import the appropriate class header before you can actually instantiate or use that class. But all of your actual usage of a given class is in the .m file, so that’s a good place to put the header import without stepping on anyone’s toes.


#6

[quote]… it can become a major issue if one header file (say Foo.h) unnecessarily includes another header file (say Bar.h) which is a few tons in weight[/quote]Surely the programmmer knows what is necessary and what is not in his own code?[quote]The existence of @class was also partially to be a solution to the “Foo.h imports Bar.h which imports Foo.h which imports Bar.h” infinite loop problem.[/quote]I thought that #import only imported a file once, whereas #include did not, which might lead to that circular reference problem. So with #import the compiler just does not obey a duplicate import directive.


#7

Hahaha, how many bugs in the world would be fixed if “Surely the programmer knows…” were true?

Indeed it does/should, but has still managed to cause problems for parallelized/distributed compilation (which, I think, has been removed from recent versions of Xcode. Hm.). So that argument may be irrelevant now.