@class vs. #import
ClassA는 ClassB 헤더를 포함해야하고 ClassB는 순환 포함을 피하기 위해 ClassA 헤더를 포함해야하는 이벤트에서 포워드 클래스 선언을 사용해야합니다. 또한 an #import
이 단순 ifndef
하므로 포함이 한 번만 발생한다는 것도 이해합니다 .
내 질문은 이것이다 : 언제 한 번 사용 #import
하고 언제 사용 @class
합니까? 때때로 @class
선언을 사용 하면 다음과 같은 일반적인 컴파일러 경고가 표시됩니다.
warning: receiver 'FooController' is a forward class and corresponding @interface may not exist.
@class
순방향 선언을 제거 #import
하고 컴파일러가 제공하는 경고를 침묵시키기 위해 던지는 대신 이것을 이해 하고 싶습니다.
이 경고가 표시되는 경우 :
경고 : 수신자 'MyCoolClass'는 포워드 클래스이며 해당 @interface가 없을 수 있습니다.
#import
파일 이 필요 하지만 구현 파일 (.m)에서이를 수행하고 @class
헤더 파일에서 선언을 사용할 수 있습니다.
@class
(보통) #import
파일에 대한 필요성을 제거하지 않고 정보가 유용한 곳에 요구 사항을 더 가깝게 이동합니다.
예를 들어
라고 말하면 @class MyCoolClass
컴파일러는 다음과 같은 내용을 볼 수 있음을 알고 있습니다.
MyCoolClass *myObject;
MyCoolClass
유효한 클래스 이외의 다른 것에 대해 걱정할 필요가 없으며 그것에 대한 포인터를위한 공간을 예약해야합니다 (실제로는 포인터). 따라서 헤더에서 @class
90 %의 시간으로 충분합니다.
그러나 myObject
의 멤버 를 만들거나 액세스 해야하는 경우 컴파일러에 해당 메서드가 무엇인지 알려야합니다. 이 시점에서 (아마도 구현 파일에서) #import "MyCoolClass.h"
컴파일러에게 "이것은 클래스입니다"이외의 추가 정보를 알려야합니다.
세 가지 간단한 규칙 :
#import
헤더 파일 (.h
파일) 의 수퍼 클래스 및 채택 된 프로토콜 만 .#import
모든 클래스 및 프로토콜은 구현에서 메시지를 보냅니다 (.m
파일).- 다른 모든 것에 대한 포워드 선언.
구현 파일에서 정방향 선언을 수행하면 아마도 뭔가 잘못되었을 것입니다.
ADC 에 대한 Objective-C 프로그래밍 언어 문서보기
클래스 정의 섹션에서 | 클래스 인터페이스는 이것이 수행되는 이유를 설명합니다.
@class 지시문은 컴파일러와 링커에서 볼 수있는 코드의 양을 최소화하므로 클래스 이름의 포워드 선언을 제공하는 가장 간단한 방법입니다. 간단하기 때문에 다른 파일을 가져 오는 파일을 가져올 때 발생할 수있는 잠재적 인 문제를 피할 수 있습니다. 예를 들어, 한 클래스가 다른 클래스의 정적으로 형식화 된 인스턴스 변수를 선언하고 두 인터페이스 파일이 서로를 가져 오는 경우 두 클래스 모두 올바르게 컴파일되지 않을 수 있습니다.
이게 도움이 되길 바란다.
필요한 경우 헤더 파일에 정방향 선언을 #import
사용하고 구현에 사용중인 모든 클래스에 대한 헤더 파일을 사용합니다. 즉, #import
구현에서 항상 사용중인 파일을 사용하고 헤더 파일에서 클래스를 참조해야하는 경우 포워드 선언도 사용합니다.
이에 대한 예외 는 #import
헤더 파일에서 상속하는 클래스 또는 공식 프로토콜 이어야한다는 것입니다 (이 경우 구현에서 가져올 필요가 없습니다).
일반적인 관행은 헤더 파일에서 @class를 사용하고 (하지만 여전히 수퍼 클래스를 #import해야 함) 구현 파일에서 #import를 사용하는 것입니다. 이것은 원형 내포물을 피할 것이며 단지 작동합니다.
또 다른 장점 : 빠른 컴파일
헤더 파일을 포함하는 경우 변경 사항으로 인해 현재 파일도 컴파일되지만 클래스 이름이 @class name
. 물론 소스 파일에 헤더를 포함해야합니다.
나의 문의는 이쪽입니다. 언제 #import를 사용하고 언제 @class를 사용합니까?
간단한 대답 : 귀하 #import
또는 #include
신체적 의존성이있을 때. 그렇지 않으면, 당신은 앞으로 선언을 사용 ( @class MONClass
, struct MONStruct
, @protocol MONProtocol
).
다음은 신체적 의존의 몇 가지 일반적인 예입니다.
- 모든 C 또는 C ++ 값 (포인터 또는 참조는 물리적 종속성이 아님). a
CGPoint
가 ivar 또는 속성 인 경우 컴파일러는CGPoint
. - 당신의 슈퍼 클래스.
- 당신이 사용하는 방법.
때때로 @class 선언을 사용하면 다음과 같은 일반적인 컴파일러 경고가 표시됩니다. "경고 : 'FooController'수신기는 포워드 클래스이며 해당 @ 인터페이스가 없을 수 있습니다."
컴파일러는 실제로 이와 관련하여 매우 관대합니다. 힌트 (위와 같은)를 드롭하지만, 무시하고 #import
제대로 하지 않으면 스택을 쉽게 폐기 할 수 있습니다 . 그래야하지만 (IMO) 컴파일러는이를 강제하지 않습니다. ARC에서 컴파일러는 참조 계수를 담당하기 때문에 더 엄격합니다. 무슨 일이 일어나면 컴파일러는 당신이 호출하는 알 수없는 메서드를 만나면 기본값으로 돌아갑니다. 모든 반환 값과 매개 변수는 id
. 따라서 물리적 의존성으로 간주되어야하므로 코드베이스에서 모든 경고를 제거해야합니다. 이것은 선언되지 않은 C 함수를 호출하는 것과 유사합니다. C를 사용하면 매개 변수가로 간주됩니다 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.
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.
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).
for extra info about file dependencies & #import & @class check this out:
http://qualitycoding.org/file-dependencies/ itis good article
summary of the article
imports in header files:
- #import the superclass you’re inheriting, and the protocols you’re implementing.
- Forward-declare everything else (unless it comes from a framework with a master header).
- Try to eliminate all other #imports.
- Declare protocols in their own headers to reduce dependencies.
- Too many forward declarations? You have a Large Class.
imports in implementation files:
- Eliminate cruft #imports that aren’t used.
- If a method delegates to another object and returns what it gets back, try to forward-declare that object instead of #importing it.
- If including a module forces you to include level after level of successive dependencies, you may have a set of classes that wants to become a library. Build it as a separate library with a master header, so everything can be brought in as a single prebuilt chunk.
- Too many #imports? You have a Large Class.
When I develop, I have only three things in mind that never cause me any problems.
- Import super classes
- Import parent classes (when you have children and parents)
- 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.
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.
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.
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.
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:
- This could be like if you are going to derive your class from it or
- 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.
Think of @class as telling the compiler "trust me, this exists".
Think of #import as copy-paste.
You want to minimize the number of imports you have for a number of reasons. Without any research, the first thing that comes to mind is it reduces compile time.
Notice that when you inherit from a class, you can't simply use a forward declaration. You need to import the file, so that the class you're declaring knows how it's defined.
This is an example scenario, where we need @class.
Consider if you wish to create a protocol within header file, which has a parameter with data type of the same class, then you can use @class. Please do remember that you can also declare protocols separately, this is just an example.
// DroneSearchField.h
#import <UIKit/UIKit.h>
@class DroneSearchField;
@protocol DroneSearchFieldDelegate<UITextFieldDelegate>
@optional
- (void)DroneTextFieldButtonClicked:(DroneSearchField *)textField;
@end
@interface DroneSearchField : UITextField
@end
참고URL : https://stackoverflow.com/questions/322597/class-vs-import
'IT박스' 카테고리의 다른 글
찾은 어셈블리의 매니페스트 정의가 어셈블리 참조와 일치하지 않습니다. (0) | 2020.09.30 |
---|---|
@property와 getter 및 setter 사용 (0) | 2020.09.30 |
로컬 및 원격 Git 리포지토리 모두의 마스터 브랜치 이름 변경 (0) | 2020.09.29 |
Linux / Unix에서 $ PATH를 영구적으로 설정하는 방법은 무엇입니까? (0) | 2020.09.29 |
배치 / cmd에서 "주석 처리"(주석 추가)하는 방법은 무엇입니까? (0) | 2020.09.29 |