Для методов Objective-C общая практика заключается в размещении методов, которые вы хотите представить, в разделе @interface
файла заголовка, чтобы другой код мог включать только .h и знать, как взаимодействовать с вашим кодом. Основанное на заказе «отложенное объявление» работает так же, как функции в C - вам не нужно объявлять прототип метода, если только у вас нет зависимости, которую нельзя решить с помощью упорядочения, но вы можете добавить прототипы методов внутри @implementation
при необходимости.
Так что да, вы на правильном пути. Не повторяйте прототип метода для унаследованных методов - компилятор находит его в заголовочном файле родителя. Методы делегата могут быть определены как прототипы в категории (привязаны к классу) и реализованы по желанию, но делегату не нужно предоставлять прототип метода, поскольку он уже определен. (Он все еще может, если хочет для ясности и т. Д.)
Поскольку вы только изучаете Objective-C, остальная часть этого ответа гораздо более детальна, чем вы просили. Вы были предупреждены. ; -)
Когда вы статически вводите переменную (например, MyClass*
вместо id
), компилятор предупредит вас, когда вы попытаетесь вызвать метод, который класс не объявляет, что он реализует, независимо от того, делает он это или нет. Если вы динамически вводите переменную, компилятор не остановит вас от вызова того, что вам нравится, и вы получите ошибки во время выполнения, только если вы вызовете что-то, что не существует. Что касается языка, вы можете вызывать любой метод, который класс реализует без ошибок во время выполнения - нет способа ограничить, кто может вызывать метод.
Лично я думаю, что это действительно хорошая вещь. Мы настолько привыкли к инкапсуляции и защите нашего кода от другого кода, что иногда мы относимся к вызывающей стороне как к обманщику, а не как к доверенному сотруднику или клиенту. Я нахожу, что довольно приятно писать с мыслью «ты делаешь свою работу, а я делаю свою», где каждый уважает границы и заботится о своем. Вы могли бы сказать, что «отношение» Objective-C - это доверие сообщества, а не строгое принуждение. Например, я с радостью помогу любому, кто придет ко мне на стол, но будет очень раздражен, если кто-то испортит мои вещи или переместит вещи без вопросов. Хорошо продуманный код не должен быть параноидальным или социопатическим, он просто должен хорошо работать вместе. : -)
Тем не менее, существует много подходов для структурирования ваших интерфейсов, в зависимости от уровня детализации, который вы хотите / нуждаетесь в представлении интерфейсов пользователям. Любые методы, которые вы объявляете в общедоступном заголовке, по сути являются честной игрой для всех. Сокрытие объявлений методов похоже на блокировку вашей машины или дома - это, вероятно, не отпустит всех, но (1) оно «держит честных людей честными», не соблазняя их чем-то, с чем им не следует связываться, и (2 ) любой, кто действительно входит, наверняка будет знать, что они не должны, и не может жаловаться на негативные последствия.
Ниже приведены некоторые соглашения, которые я использую для именования файлов, и то, что идет в каждом файле - начиная с файла .m внизу, каждый файл содержит файл над ним. (Использование строгой цепочки включений предотвратит такие вещи, как предупреждения о дублировании символов.) Некоторые из этих уровней применимы только к более крупным повторно используемым компонентам, таким как платформы Какао. Адаптируйте их в соответствии со своими потребностями и используйте любые имена, которые вам подходят.
MyClass.h
- Открытый API (интерфейс прикладного программирования)
MyClass_Private.h
- Внутренний SPI (интерфейс системного программирования)
MyClass_Internal.h
- Внутренний проектный IPI (внутренний интерфейс программирования)
MyClass.m
- Реализация, как правило, всех объявлений API / SPI / IPI
MyClass_Foo.m
- дополнительная реализация, например для категорий
API для Евыryone для использования, и публично поддерживается (обычно в Foo.framework/Headers
). SPI предоставляет дополнительные функциональные возможности для внутренних клиентов вашего кода, но с учетом того, что поддержка может быть ограничена и интерфейс может быть изменен (обычно в Foo.framework/PrivateHeaders
). IPI состоит из специфических для реализации деталей, которые никогда не должны использоваться вне самого проекта, и эти заголовки вообще не включены в структуру. Любой, кто решает использовать вызовы SPI и IPI, делает это на свой страх и риск, и обычно в ущерб, когда изменения нарушают их код. : -)