Вопрос

Я изучаю Objective-C и имею опыт работы с C/C++.

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

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

  • Теперь, в Objective-C, кажется, что вам нужно объявлять селекторы в заголовочном файле только в том случае, если они будут использоваться чем-то внешним, и что вы можете прекрасно создавать селекторы в своем .m-файле и вызывать их внутри файл .m.Кроме того, похоже, что методы делегата или унаследованные методы никогда не определяются (пере)определяются.

Я на правильном пути?Когда вам нужно определить селектор в Objective-C?

Это было полезно?

Решение

Для методов Objective-C общепринятой практикой является размещение методов, которые вы хотите предоставить, в @interface раздел заголовочного файла, чтобы другой код мог включать только расширение .h и знать, как взаимодействовать с вашим кодом.«Отложенное объявление» на основе порядка работает так же, как функции в C. придется объявляйте прототип метода, если у вас нет зависимости, которую нельзя разрешить путем упорядочивания, но вы можете добавлять прототипы методов внутри @implementation если нужно.

Так что да, вы на правильном пути.Не повторяйте прототип метода для унаследованных методов — компилятор находит его в заголовочном файле родительского метода.Методы делегата могут быть определены как прототипы в категории (прикреплены к классу) и реализованы по желанию, но делегату не требуется предоставлять прототип метода, поскольку он уже определен.(Он все еще может, если захочет, для ясности и т. д.)

Поскольку вы только изучаете Objective-C, остальная часть этого ответа гораздо более подробна, чем вы просили.Вы были предупреждены.;-)


Когда вы статически вводите переменную (например, MyClass* вместо id) компилятор предупредит вас, когда вы попытаетесь вызвать метод, который класс не объявляет о своей реализации, независимо от того, реализует он это или нет.Если вы динамически вводите переменную, компилятор не будет мешать вам вызывать все, что захотите, и вы получите ошибки во время выполнения только в том случае, если вы вызовете что-то, чего не существует.Что касается языка, вы можете вызвать любой метод, реализуемый классом, без ошибок во время выполнения — невозможно ограничить круг лиц, которые могут вызывать метод.

Лично я считаю, что это на самом деле хорошо.Мы настолько привыкли к инкапсуляции и защите нашего кода от другого кода, что иногда относимся к вызывающему абоненту как к коварному злодею, а не как к заслуживающему доверия коллеге или клиенту.Я считаю, что довольно приятно писать код с мышлением «вы делаете свою работу, а я — свою», когда каждый уважает границы и заботится о своем.Вы могли бы сказать, что «отношение» Objective-C основано на доверии сообщества, а не на строгом принуждении.Например, я рад помочь любому, кто подходит ко мне на стол, но меня бы очень раздражало, если бы кто-то испортил мои вещи или передвинул вещи без моей просьбы.Хорошо спроектированный код не обязательно должен быть параноиком или социопатом, он просто должен хорошо работать вместе.:-)

Тем не менее, существует множество подходов к структурированию ваших интерфейсов, в зависимости от уровня детализации, который вам нужен/нужен при предоставлении интерфейсов пользователям.Любые методы, которые вы объявляете в общедоступном заголовке, по сути являются честной игрой, которую может использовать каждый.Сокрытие объявлений методов немного похоже на запирание машины или дома — оно, вероятно, не защитит всех, но (1) оно «сохраняет честность честных людей», не соблазняя их чем-то, с чем им не следует связываться, и (2 ) любой, кто делает войти, наверняка будут знать, что им этого делать не следовало, и не смогут жаловаться на негативные последствия.

Ниже приведены некоторые соглашения, которые я использую для именования файлов, и то, что содержится в каждом файле — начиная с файла .m внизу, каждый файл включает в себя файл над ним.(Использование строгой цепочки включений предотвратит такие вещи, как предупреждения о дублировании символов.) Некоторые из этих уровней применимы только к более крупным компонентам многократного использования, таким как платформы Cocoa.Адаптируйте их в соответствии со своими потребностями и используйте любые имена, которые вам подходят.

  • MyClass.h — Публичный API (интерфейс прикладного программирования)
  • MyClass_Private.h — Внутренний SPI (интерфейс системного программирования) компании.
  • MyClass_Internal.h — Внутренний IPI проекта (внутренний программный интерфейс)
  • MyClass.m — Реализация, как правило, всех деклараций API/SPI/IPI.
  • MyClass_Foo.m — Дополнительная реализация, например для категорий

API предназначен для использования всеми и поддерживается публично (обычно в Foo.framework/Headers).SPI предоставляет дополнительную функциональность для внутренних клиентов вашего кода, но с учетом того, что поддержка может быть ограничена, а интерфейс может быть изменен (обычно в Foo.framework/PrivateHeaders).IPI состоит из деталей, специфичных для реализации, которые никогда не следует использовать вне самого проекта, и эти заголовки вообще не включены в структуру.Любой, кто решает использовать вызовы SPI и IPI, делает это на свой страх и риск и обычно себе во вред, когда изменения нарушают его код.:-)

Другие советы

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

Кроме того, если вы определите метод в файле .m над любым кодом, который его вызывает (ленивое объявление), то это не будет генерировать никаких предупреждений.Однако применимо то же самое: вы можете отправить сообщение объекту без его объявления.

Конечно — это значит, что в Objective-C нет приватных методов.Можно вызвать любой метод, реализуемый классом.

Личное предпочтение.Если это общедоступный метод (т.е. используемый извне).объявите это в .h и определите в .m.Если вы хотите ограничить его видимость или хотя бы указать, что это частный метод, используйте расширения категорий/классов в файле .m.Хотя во многих примерах кода используется метод ленивого объявления.

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

Это может быть очень мощно, но является источником путаницы для начинающих программистов Obj-C, особенно тех, кто работает на C++, Java или C#.Вот основные практические правила:

  • Вы должны определить все общедоступные методы в своем @interface, чтобы потребители знали, какие сообщения вы собираетесь обрабатывать.
  • Вам следует определить методы @private в вашем @interface, чтобы избежать сообщений компилятора и избежать необходимости упорядочивать методы в вашей @implementation.
  • Вам следует использовать протоколы при реализации определенного соглашения о методах вашего класса.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top