Когда я определяю методы target-c? - PullRequest
34 голосов
/ 20 июня 2009

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

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

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

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

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

Ответы [ 3 ]

78 голосов
/ 20 июня 2009

Для методов 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, делает это на свой страх и риск, и обычно в ущерб, когда изменения нарушают их код. : -)

6 голосов
/ 20 июня 2009

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

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

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

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

3 голосов
/ 20 июня 2009

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

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

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

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

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