Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 630 Vote(s) - 3.52 Average
  • 1
  • 2
  • 3
  • 4
  • 5
@class vs. #import

#1
It is to my understanding that one should use a forward-class declaration in the event ClassA needs to include a ClassB header, and ClassB needs to include a ClassA header to avoid any circular inclusions. I also understand that an `#import` is a simple `ifndef` so that an include only happens once.

My inquiry is this: When does one use `#import` and when does one use `@class`? Sometimes if I use a `@class` declaration, I see a common compiler warning such as the following:

> `warning: receiver 'FooController' is a forward class and corresponding @interface may not exist.`

Would really love to understand this, versus just removing the `@class` forward-declaration and throwing an `#import` in to silence the warnings the compiler is giving me.
Reply

#2
The common practice is using @class in header files (but you still need to #import the superclass), and #import in implementation files. This will avoid any circular inclusions, and it just works.
Reply

#3
Use a forward declaration in the header file if needed, and `#import` the header files for any classes you're using in the implementation. In other words, you always `#import` the files you're using in your implementation, and if you need to reference a class in your header file use a forward declaration as well.

The **exception** to this is that you should `#import` a class or formal protocol you're inheriting from in your header file (in which case you wouldn't need to import it in the implementation).
Reply

#4
When I develop, I have only three things in mind that never cause me any problems.

1. Import super classes
2. Import parent classes (when you have children and parents)
3. Import classes outside your project (like in frameworks and libraries)

For all other classes (subclasses and child classes in my project self), I declare them via forward-class.
Reply

#5
I see a lot of "Do it this way" but I don't see any answers to "Why?"

So: *Why* should you @class in your header and #import only in your implementation? You're doubling your work by having to @class *and* #import all the time. Unless you make use of inheritance. In which case you'll be #importing multiple times for a single @class. Then you have to remember to remove from multiple different files if you suddenly decide you don't need access to a declaration anymore.

Importing the same file multiple times isn't an issue because of the nature of #import.
Compiling performance isn't really an issue either. If it were, we wouldn't be #importing Cocoa/Cocoa.h or the like in pretty much every header file we have.

Reply

#6
if we do this

@interface Class_B : Class_A

mean we are inheriting the Class_A into Class_B, in Class_B we can access all the variables of class_A.

if we are doing this

#import ....
@class Class_A
@interface Class_B

here we saying that we are using the Class_A in our program, but if we want to use the Class_A variables in Class_B we have to #import Class_A in .m file(make a object and use it's function and variables).
Reply

#7
Forward declaration just to the prevent compiler from showing error.

the compiler will know that there is class with the name you've used in your header file to declare.
Reply

#8
If you try to declare a variable, or a property in your header file, which you didn't import yet, your gonna get an error saying that the compiler doesn't know this class.

Your first thought is probably `#import` it.<br />
This may cause problems in some cases.

For example if you implement a bunch of C-methods in the header file, or structs, or something similar, because they shouldn't be imported multiple times.

Therefore you can tell the compiler with `@class`:

> I know you don't know that class, but it exists. It's going to be imported or implemented elsewhere

It basically tells the compiler to shut up and compile, even though it's not sure if this class is ever going to be implemented.

You will usually use `#import` in the **.m** and `@class` in the **.h** files.
Reply

#9
> My inquiry is this. When does one use #import and when does one use @class?

Simple answer: You `#import` or `#include` when there is a physical dependency. Otherwise, you use forward declarations (`@class MONClass`, `struct MONStruct`, `@protocol MONProtocol`).

Here are some common examples of physical dependence:

- Any C or C++ value (a pointer or reference is not a physical dependency). If you have a `CGPoint` as an ivar or property, the compiler will need to see the declaration of `CGPoint`.
- Your superclass.
- A method you use.

> Sometimes if I use a @class declaration, I see a common compiler warning such as the following:
> "warning: receiver 'FooController' is a forward class and corresponding @interface may not exist."

The compiler's actually very lenient in this regard. It will drop hints (such as the one above), but you can trash your stack easily if you ignore them and don't `#import` properly. Although it should (IMO), the compiler does not enforce this. In ARC, the compiler is more strict because it is responsible for reference counting. What happens is the compiler falls back on a default when it encounters an unknown method which you call. Every return value and parameter is assumed to be `id`. Thus, you ought to eradicate every warning from your codebases because this should be considered physical dependence. This is analogous to calling a C function which is not declared. With C, parameters are assumed to be `int`.

The reason you would favor forward declarations is that you can reduce your build times by factors because there is minimal dependence. With forward declarations, the compiler sees there is a name, and can correctly parse and compile the program without seeing the class declaration or all of its dependencies when there is no physical dependency. Clean builds take less time. Incremental builds take less time. Sure, you will end up spending a little more time making sure the all the headers you need are visible to every translation as a consequence, but this pays off in reduced build times quickly (assuming your project is not tiny).

If you use `#import` or `#include` instead, you're throwing a lot more work at the compiler than is necessary. You're also introducing complex header dependencies. You can liken this to a brute-force algorithm. When you `#import`, you're dragging in tons of unnecessary information, which requires a lot of memory, disk I/O, and CPU to parse and compile the sources.

ObjC is pretty close to ideal for a C based language with regards to dependency because `NSObject` types are never values -- `NSObject` types are always reference counted pointers. So you can get away with incredibly fast compile times if you structure your program's dependencies appropriately and forward where possible because there is very little physical dependence required. You can also declare properties in the class extensions to further minimize dependence. That's a huge bonus for large systems -- you would know the difference it makes if you have ever developed a large C++ codebase.

Therefore, my recommendation is to use forwards where possible, and then to `#import` where there is physical dependence. If you see the warning or another which implies physical dependence -- fix them all. The fix is to `#import` in your implementation file.

As you build libraries, you will likely classify some interfaces as a group, in which case you would `#import` that library where physical dependence is introduced (e.g. `#import <AppKit/AppKit.h>`). This can introduce dependence, but the library maintainers can often handle the physical dependencies for you as needed -- if they introduce a feature, they can minimize the impact it has on your builds.
Reply

#10
Compiler will complain only if you are going to use that class in such a way that the compiler needs to know its implementation.

Ex:

1. This could be like if you are going to derive your class from it or
2. If you are going to have an object of that class as a member variable (though rare).

It will not complain if you are just going to use it as a pointer. Of course, you will have to #import it in the implementation file (if you are instantiating an object of that class) since it needs to know the class contents to instantiate an object.

NOTE: #import is not same as #include. This means there is nothing called circular import. import is kind of a request for the compiler to look into a particular file for some information. If that information is already available, compiler ignores it.

Just try this, import A.h in B.h and B.h in A.h. There will be no problems or complaints and it will work fine too.

**When to use @class**

You use @class only if you don't even want to import a header in your header. This could be a case where you don't even care to know what that class will be. Cases where you may not even have a header for that class yet.

An example of this could be that you are writing two libraries. One class, lets call it A, exists in one library. This library includes a header from the second library. That header might have a pointer of A but again might not need to use it. If library 1 is not yet available, library B will not be blocked if you use @class. But if you are looking to import A.h, then library 2's progress is blocked.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through