Objective-C: прямое объявление класса

Я пишу приложение с несколькими представлениями, в котором для переключения между представлениями используется класс RootViewController.

В моем заголовке MyAppDelegate я создаю экземпляр RootViewController с именем rootViewController. Я видел такие примеры, когда директива @class использовалась как «объявление прямого класса», но я не совсем уверен, что это означает или чего добивается.

#import <UIKit/UIKit.h>
@class RootViewController;
@interface MyAppDelegate
.
.
.

person Old McStopher    schedule 04.03.2011    source источник
comment
Я предполагаю, что вы не создаете экземпляр, а просто объявляете указатель на. Это правильно?   -  person Roger C S Wernersson    schedule 14.01.2013


Ответы (3)


По сути, он сообщает компилятору, что класс RootViewController существует, без указания того, как именно он выглядит (то есть: его методы, свойства и т. Д.). Вы можете использовать это для написания кода, который включает RootViewController переменные-члены, без необходимости включать полное объявление класса.

Это особенно полезно при разрешении циклических зависимостей - например, где, скажем, ClassA имеет член типа ClassB*, а ClassB имеет член типа ClassA*. Вам необходимо объявить ClassB, прежде чем вы сможете использовать его в ClassA, но вам также необходимо объявить ClassA, прежде чем вы сможете использовать его в ClassB. Форвардные объявления позволяют преодолеть это, сообщая ClassA, что ClassB существует, без необходимости фактически указывать ClassB's полную спецификацию.

Другая причина, по которой вы, как правило, находите много форвардных объявлений, заключается в том, что некоторые люди принимают соглашение о форвардном объявлении классов, если только они не обязательно должны включать полное объявление. Я не совсем помню, но, возможно, это то, что Apple рекомендует в своих руководящих принципах по стилю Objective-C.

Продолжая мой пример выше, если ваши объявления ClassA и ClassB находятся в файлах ClassA.h и ClassB.h соответственно, вам нужно #import в зависимости от того, какой из них будет использовать его объявление в другом классе. Использование прямого объявления означает, что вам не нужен #import, что делает код красивее (особенно, когда вы начинаете собирать довольно много классов, каждому из которых потребуется `#import там, где он используется), и увеличивает производительность компиляции за счет минимизации количества кода, который компилятор должен учитывать при компиляции любого заданного файла.

В стороне, хотя вопрос касается исключительно форвардных объявлений в Objective-C, все последующие комментарии также в равной степени применимы к кодированию на C и C ++ (и, вероятно, многих других языках), которые также поддерживают форвардное объявление и обычно используют его для те же цели.

person Mac    schedule 04.03.2011
comment
Итак, я думаю, я не понимаю, почему недостаточно создать объект RootViewController в MyAppDelegate.h. Кажется избыточным, но я уверен, что упускаю что-то фундаментальное. ... РЕДАКТИРОВАТЬ: Ах; только что видел вашу правку. - person Old McStopher; 04.03.2011
comment
Отлично. Лаконично. Спасибо. - person Old McStopher; 04.03.2011
comment
Одна из причин для пересылки классов объявления заключается в том, что A имеет указатель на B, который имеет указатель на A. Вы не можете импортировать A.h из B.h И B.h из A.h, потому что это циклическая зависимость. Об этом позаботится предварительное объявление в файлах заголовков. A.m импортирует B.h. B.m импорт A.h. - person Roger C S Wernersson; 11.01.2013
comment
@RogerWernersson: это не совсем то, о чем говорится в моем ответе? - person Mac; 12.01.2013
comment
Тогда можем ли мы использовать @class вместо импорта для любого другого случая? Или в каком случае абсолютно необходимо импортировать и нельзя выполнить с помощью @class? - person Dennis Setiawan; 21.05.2021

Форвардные объявления в основном предназначены для того, чтобы избежать циклического импорта, когда один файл импортирует другой файл, который импортирует первый файл и т. Д. В основном, когда вы импортируете файл, содержимое файла заменяется в точке импорта, когда вы строите свой проект, который затем загружается компилятору. Если у вас есть циклический импорт, у вас будет бесконечный цикл, который никогда не будет компилироваться. К счастью, xcode сообщит вам об этом перед попыткой. В прямом объявлении говорится: «Не импортируйте этот класс, а просто знайте, что он существует». Без импорта или прямого объявления вы получите сообщение об ошибке, что такого класса не существует.

person Aks    schedule 05.06.2018

@class или forward class declaration (неполный тип) - просто сообщите компилятору, что этот класс существует. В этом случае компилятор ничего не знает о структуре памяти типов - размере класса, членах или методах. Вот почему вы можете использовать для определения классов только ссылки и указатели.

Преимущества:

  • сократить время сборки
  • разбивать циклические ссылки
person yoAlex5    schedule 06.12.2019