@class vs. #import - PullRequest
       102

@class vs. #import

704 голосов
/ 27 ноября 2008

Насколько я понимаю, следует использовать объявление прямого класса в случае, если ClassA необходимо включить заголовок ClassB, а ClassB должен включить заголовок ClassA, чтобы избежать каких-либо циклических включений. Я также понимаю, что #import - это простое ifndef, поэтому включение происходит только один раз.

Мой вопрос таков: когда один использует #import и когда один использует @class? Иногда, если я использую объявление @class, я вижу общее предупреждение компилятора, например следующее:

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

Очень хотелось бы понять это, вместо того, чтобы просто удалить @class forward-объявление и добавить #import, чтобы заставить замолчать предупреждения, которые компилятор дает мне.

Ответы [ 16 ]

3 голосов
/ 07 января 2013

Если вы попытаетесь объявить переменную или свойство в вашем заголовочном файле, который вы еще не импортировали, вы получите ошибку, сообщающую, что компилятор не знает этот класс.

Ваша первая мысль, вероятно, #import это.
Это может вызвать проблемы в некоторых случаях.

Например, если вы реализуете группу C-методов в заголовочном файле, или структурах, или что-то подобное, потому что они не должны импортироваться несколько раз.

Поэтому вы можете указать компилятору @class:

Я знаю, что вы не знаете этот класс, но он существует. Он будет импортирован или реализован в другом месте

Он в основном говорит компилятору закрыть и скомпилировать, даже если он не уверен, будет ли когда-либо реализован этот класс.

Обычно вы будете использовать #import в .m и @class в .h файлах.

3 голосов
/ 18 мая 2011

Когда я развиваюсь, я имею в виду только три вещи, которые никогда не вызывают у меня никаких проблем.

  1. Импорт суперклассов
  2. Импорт родительских классов (если у вас есть дети и родители)
  3. Импорт классов вне вашего проекта (как в фреймворках и библиотеках)

Для всех других классов (подклассы и дочерние классы в моем проекте self) я объявляю их через forward-класс.

0 голосов
/ 04 января 2018

Представьте, что @class говорит компилятору: «Поверьте мне, это существует».

Думайте о #import как о копи-пасте.

Вы хотите свести к минимуму количество ваших импортных операций по ряду причин. Без каких-либо исследований первое, что приходит на ум, - это сокращение времени компиляции.

Обратите внимание, что когда вы наследуете от класса, вы не можете просто использовать предварительное объявление. Вам нужно импортировать файл, чтобы объявленный вами класс знал, как он определен.

0 голосов
/ 27 сентября 2016

Это пример сценария, где нам нужен @class.

Рассмотрим, если вы хотите создать протокол в заголовочном файле, в котором есть параметр с типом данных того же класса, тогда вы можете использовать @class. Пожалуйста, помните, что вы также можете объявлять протоколы отдельно, это только пример.

// DroneSearchField.h

#import <UIKit/UIKit.h>
@class DroneSearchField;
@protocol DroneSearchFieldDelegate<UITextFieldDelegate>
@optional
- (void)DroneTextFieldButtonClicked:(DroneSearchField *)textField;
@end
@interface DroneSearchField : UITextField
@end
0 голосов
/ 18 июля 2013

Компилятор будет жаловаться только в том случае, если вы собираетесь использовать этот класс таким образом, что компилятору необходимо знать его реализацию.

Ex:

  1. Это может быть похоже на то, если вы собираетесь извлечь из него свой класс, или
  2. Если вы собираетесь использовать объект этого класса в качестве переменной-члена (хотя и редко).

Он не будет жаловаться, если вы просто собираетесь использовать его в качестве указателя. Конечно, вам нужно будет #import его в файле реализации (если вы создаете экземпляр объекта этого класса), так как он должен знать содержимое класса, чтобы создать экземпляр объекта.

ПРИМЕЧАНИЕ: #import отличается от #include. Это означает, что нет ничего, что называется круговым импортом. import - это своего рода запрос компилятора на поиск определенного файла для получения определенной информации. Если эта информация уже доступна, компилятор игнорирует ее.

Просто попробуйте это, импортируйте A.h в B.h и B.h в A.h. Там не будет никаких проблем или жалоб, и это будет работать нормально.

Когда использовать @ class

Вы используете @class, только если вы даже не хотите импортировать заголовок в свой заголовок. Это может быть случай, когда вам даже не важно знать, что это будет за класс. Случаи, когда у вас может даже не быть заголовка для этого класса.

Примером этого может быть то, что вы пишете две библиотеки. Один класс, назовем его A, существует в одной библиотеке. Эта библиотека содержит заголовок из второй библиотеки. Этот заголовок может иметь указатель A, но, опять же, может не потребоваться его использование. Если библиотека 1 еще не доступна, библиотека B не будет заблокирована, если вы используете @class. Но если вы хотите импортировать A.h, то прогресс библиотеки 2. будет заблокирован.

0 голосов
/ 22 июня 2012

Переадресация только для того, чтобы компилятор не показывал ошибку.

компилятор будет знать, что существует класс с именем, которое вы использовали в своем заголовочном файле для объявления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...