Проблемы с предварительными объявлениями и файлами заголовков

Чтобы сократить время сборки, а также сделать мой код как можно более кратким, я использовал предварительные объявления в своих файлах заголовков и помещал свои операторы #import в файлы реализации. До сих пор это работало отлично, однако я столкнулся с проблемой. Предположим, у меня есть класс MyClass, который возвращает объект класса Widget, например:

@interface MyClass : NSObject
-(Widget*)widgetWithName:(NSString*)name;
@end

Предположим, что у Widget есть метод -(void)arbitraryMethod;

Теперь предположим, что я реализую класс, который импортирует MyClass.h, создает экземпляр объекта MyClass, выполняет widgetWithName:, а затем пытается отправить сообщение arbitraryMethod возвращаемому Widget, я получаю сообщение об ошибке receiver type "Widget" for instance message is a forward declaration. Итак, я должен продолжить и импортировать заголовочный файл Widget.h, чтобы исправить ошибку.

Конечно, это не проблема, когда я возвращаю классы Foundation, потому что #import <Foundation/Foundation.h> находится в Prefix.pch.

Какова наилучшая практика? Я чувствую, что если я возвращаю класс или использую этот класс в качестве аргумента в общедоступном методе, файл заголовка должен быть включен в мой файл заголовка. В противном случае, если бы у меня был класс, использующий десять разных неосновных классов в публичных методах, моим пользователям пришлось бы выискивать и импортировать новый заголовочный файл в свой проект каждый раз, когда они хотели использовать этот метод.

Это правильно или есть лучший шаблон для использования?


person Stephen Melvin    schedule 07.01.2013    source источник


Ответы (2)


Вы не можете пропустить импорт заголовков в своем заголовке до такой степени, что вы не импортируете заголовки для классов, которые используете в своих возвращаемых типах. Я предполагаю, что в таких обстоятельствах вы бы использовали @class Widget; в заголовке MyClass. Вы не можете вызвать метод для объекта, тип которого объявлен исключительно вперед с помощью @class, потому что, насколько я помню, Бум сказал, что у компилятора нет необходимых данных. По сути, вы ничего не сказали ему о классе, за исключением того, что «он существует» благодаря использованию @class, который обычно используется только для разрыва циклических ссылок. Я думаю, что настолько чистым, насколько это возможно, является импорт заголовков для классов, которые вы используете внутри своей реализации, но, как вы сказали, импорт заголовков любых классов, используемых в качестве типов возврата и аргумента в общедоступных методах в вашем заголовке.

person Metabble    schedule 07.01.2013

Вы все делаете правильно.

Да, вам нужно импортировать как MyClass.h, так и Widget.h в другой файл реализации вашего класса. Вам необходимо импортировать Widget.h, потому что на самом деле вы используете класс Widget, вызывая метод для указателя объекта типа Widget *. В файле реализации вы должны импортировать заголовок для каждого класса, который фактически используется; вам никогда не придется заботиться о том, какие заголовки MyClass.h импортирует или не импортирует (он должен импортировать как можно меньше, как вы делаете).

person user102008    schedule 07.01.2013