@Class useless?


#1

@Class BNRAsset, declared in BNREmployee.h is supposed to make the compilation of the file faster.

But you still have to #import “BNRAsset.h” in the BNREmployee.m to make compiling successful.

The proposed code is:

In BNREmployee.h:
#import “BNRPerson.h”
@class BNRAsset;

in BNREmployee.m
#import “BNREmployee.h”
#import “BNRAsset.h”

in main.m
#import “BNREmployee.h”
#import “BNRAsset.h”

BNRAsset.h still needs to be included in the compilation at some time!

Instead:

In BNREmployee.h:
#import “BNRPerson.h”
#import “BNRAsset.h”

in BNREmployee.m
#import “BNREmployee.h”

in main.m
#import “BNREmployee.h”

Just works fine.

There seems to be no advantage to use @Class… To the contrary.


#2

I too don’t see the need for it (yet). Sure we are touching lightly, and don’t need full scope, but doesn’t the compiler only import any file just ONCE? Import it now, or later, still has to be imported to compile.


#3

@class Foo construct, also known as a forward declaration of Foo, is NOT useless.

This construct enables the compiler to continue to compile in cases where it does not need to know about the full details of a class.

When compiling a header file, for example:

// Person.h

#import <Foundation/Foundation.h>

// Forward declare Address
@class Address;

@interface Person: NSObject
{
   NSString * _name;
   Address  * _address;
}

@end

When processing the Person.h file, the compiler does not need to know about the full details of the Address class because the code is only declaring a pointer to it. The compiler only needs to know that Address is a class type defined somewhere.

However, when compiling the .m file:

// Person.m

#import "Person.h"
#import "Address.h"

@implemetation Person
...

- (void)modifyAddressZipCode:(NSUInteger)zipCode ...
{
   _address.zipCode = zipCode;
   ...
}
...
@end

The compiler does need to know about the full details of the Address class because it needs to check that the Address class does indeed have a property named zipCode.

Here is another example:

struct Node {
    struct Node *parent;
    struct Node *next;
    struct Node *previous;
    struct Data *data;
};

Where the compiler does not need to know about the full details of Data type.

Therefore, forward declarations are very useful because they enable the compiler to avoid unnecessarily reading in header files.


#4

But it doesn’t change a thing!

If I hit when I am in BNREmployee.h with @Class …, and I omit #import “BNRAsset.h” in BNREmployee.m, I get a build error.

I have to #import “BNRAsset.h” somewhere else in my program.

Since #import takes care of redundancy, the presence of @Class should have no impact whatsoever on compile time: I will always have to compile “BNRAsset.h” once…

Unless I am missing something… Are there cases where @Class saves you from eventually importing a .h file?

Since we are talking of allegedly saving compile time, I suppose we are talking about using @Class in big programs.

Doesn’t that complicate the housekeeping?


#5

To understand the benefits of forward declarations, imagine that you have only Person.h. You can still compile your code, using the Person class, without having any access to Address.h thanks to the forward declaration @class Address in Person.h. Without this forward declaration, you must have access to Address.h to compile your code.

We can also use forward declarations to prevent circular #imports:

@class Bar;
@interface Foo: NSObject

- (Bar *)bar;

@end
@class Foo;
@interface Bar: NSObject

- (Foo *)foo;

@end

#6

[quote=“ibex10”]To understand the benefits of forward declarations, imagine that you have only Person.h and Person.o (the compiled form of Person.m) and you don’t have Person.m.

You can still use the Person class in your code without having to import the Address.h file provided that you don’t access anything from the address property.[/quote]

Sorry, but I am not seeing the relevance of having an .m or not of a class. I can @class, @import, #import or #include the .h file regardless of having an .m or .o file laying about.

The benefit of @class seems to lay in that I can ‘import’ a file for my .h file to use, without automatically handing off the import to everyone else who imports my .h file, but I must then double up and ‘import’ twice. Once for real in the .m file, and once as a hint in my .h file. It could lower dependency count and decrease compile time for huge systems.

Seems like a best practice for complex systems… Like Hungarian notation. Useful, but with pros ad cons…