Определение классов
Когда Вы пишете программное обеспечение для OS X или iOS, большая часть Вашего времени проведена, работая с объектами. Объекты в Objective C точно так же, как объекты на других языках объектно-ориентированного программирования: они упаковывают данные со связанным поведением.
Приложение создается как большая экосистема соединенных объектов, связывающихся друг с другом для решения определенных проблем, таких как отображение визуального интерфейса, ответ на ввод данных пользователем или хранить информацию. Для OS X или разработки iOS, Вы не должны создавать объекты с нуля для решения каждой мыслимой проблемы; вместо этого Вы имеете крупную библиотеку в наличии существующих объектов для Вашего использования, предоставленного Какао (для OS X) и Касание Какао (для iOS).
Некоторые из этих объектов сразу применимы, таковы как типы исходных данных как строки и числа, или кнопки Мне нравится элементов пользовательского интерфейса и табличные представления. Некоторые разработаны для Вас для настройки с собственным кодом для поведения в способе, которым Вы требуете. Процесс разработки приложений включает решение, как лучше всего настроить и объединить объекты, предоставленные базовыми платформами Ваши собственные объекты дать Вашему приложению его уникальный набор функций и функциональности.
В условиях объектно-ориентированного программирования объект является экземпляром класса. Эта глава демонстрирует, как определить классы в Objective C путем объявления интерфейса, описывающего способ, которым Вы предназначаете класс и его экземпляры, которые будут использоваться. Этот интерфейс включает список сообщений, что класс может получить, таким образом, также необходимо обеспечить реализацию класса, содержащую код, который будет выполняться в ответ на каждое сообщение.
Классы являются проектами объектов
Класс описывает поведение и свойства, характерные для любого определенного типа объекта. Для строкового объекта (в Objective C, это - экземпляр класса NSString
), класс предлагает различные способы исследовать и преобразовать внутренние символы, которые он представляет. Точно так же класс раньше описывал объект числа (NSNumber
) функциональность предложений вокруг внутреннего числового значения, такого как преобразование того значения к различному числовому типу.
Таким же образом то кратное число, здания, созданные из того же проекта, идентичны в структуре, каждом экземпляре класса, совместно использует те же свойства и поведение как все другие экземпляры того класса. Каждый NSString
экземпляр ведет себя таким же образом, независимо от внутренней строки символов, которые это содержит.
Любой определенный объект разработан, чтобы использоваться в особенных методах. Вы могли бы знать, что строковый объект представляет некоторую строку символов, но Вы не должны знать, что точные внутренние механизмы раньше хранили те символы. Вы не знаете, что что-либо о внутреннем поведении, используемом самим объектом, работает непосредственно с его символами, но действительно необходимо знать, как Вы, как ожидают, будете взаимодействовать с объектом, возможно будете просить у него определенные символы или запрашивать новый объект, в котором все исходные символы преобразовываются в верхний регистр.
В Objective C интерфейс класса указывает точно, как данный тип объекта предназначается, чтобы использоваться другими объектами. Другими словами, это определяет открытый интерфейс между экземплярами класса и внешнего мира.
Переменчивость определяет, может ли быть изменено представленное значение
Некоторые классы определяют объекты, которые являются неизменными. Это означает, что внутреннее содержание должно быть установлено, когда объект создается и не может впоследствии быть изменен другими объектами. В Objective C, все основные NSString
и NSNumber
объекты являются неизменными. Если необходимо представлять различное число, необходимо использовать новое NSNumber
экземпляр.
Некоторые неизменные классы также предлагают непостоянную версию. Если в частности необходимо изменить содержание строки во время выполнения, например путем добавления символов, поскольку они получены по сетевому соединению, можно использовать экземпляр NSMutableString
класс. Экземпляры этого класса ведут себя точно так же, как NSString
объекты, за исключением того, что они также предлагают функциональность для изменения символов, которые представляет объект.
Несмотря на то, что NSString
и NSMutableString
различные классы, у них есть много общих черт. Вместо того, чтобы писать два абсолютно отдельных класса с нуля, которые просто, оказывается, имеют некоторое подобное поведение, оно целесообразно использовать наследование.
Классы наследовались от других классов
В мире природы таксономия классифицирует животных в группы с условиями как разновидности, род и семья. Эти группы являются иерархическими, такими, что многократные разновидности могут принадлежать одному роду и многократным родам одной семье.
У горилл, людей, и орангутанов, например, есть много очевидных общих черт. Несмотря на то, что каждый из них принадлежит различным разновидностям, и даже различным родам, племенам и подсемьям, они таксономически связаны, так как они все принадлежат той же семье (названный «Hominidae»), как показано на рисунке 1-1.
В мире объектно-ориентированного программирования объекты также категоризированы в иерархические группы. Вместо того, чтобы использовать отличные термины для различных иерархических уровней, таких как род или разновидности, объекты просто организованы в классы. Таким же образом то, что люди наследовали определенные характеристики как элементы семьи Hominidae, класс может быть установлен наследовать функциональность от родительского класса.
Когда один класс наследовался от другого, дочерний элемент наследовал все поведение и свойства, определенные родителем. Это также имеет возможность или определить ее собственное дополнительное поведение и свойства, или переопределить поведение родителя.
В случае строковых классов Objective C, описания класса для NSMutableString
указывает, что класс наследовался от NSString
, как показано на рисунке 1-2. Вся функциональность, предоставленная NSString
доступно в NSMutableString
, такой как запросы определенных символов или запрос новых прописных строк, но NSMutableString
добавляют методы, позволяющие Вам добавлять, вставлять, заменять или удалять подстроки и отдельные символы.
Корневой класс обеспечивает базовую функциональность
Таким же образом тот весь живые организмы совместно используют некоторые основные «жизненные» характеристики, некоторая функциональность распространена через все объекты в Objective C.
Когда объект Objective C должен будет работать с экземпляром другого класса, ожидается, что другой класс предлагает определенные основные характеристики и поведение. Поэтому Objective C определяет корневой класс, от которого подавляющее большинство других классов наследовались, вызванный NSObject
. Когда один объект встретится с другим объектом, он ожидает быть в состоянии взаимодействовать с помощью, по крайней мере, основное поведение, определенное NSObject
описание класса.
При определении собственных классов необходимо как минимум наследоваться от NSObject
. В целом необходимо найти, что Касание Какао или Какао возражает, что предлагает самую близкую функциональность тому, в чем Вы нуждаетесь и наследовали от этого.
Если Вы хотите определить пользовательскую кнопку для использования в приложении для iOS, например, и предоставленное UIButton
класс не предлагает достаточно настраиваемых атрибутов для удовлетворения потребностей, имеет больше смысла создавать новый класс, наследовавшийся из UIButton
чем от NSObject
. Если Вы просто наследовались от NSObject
, необходимо было бы копировать все сложные визуальные взаимодействия и коммуникацию, определенную UIButton
класс только, чтобы заставить Вашу кнопку вести себя в пути, ожидаемом пользователем. Кроме того, путем наследования от UIButton
, Ваш подкласс автоматически получает любые будущие улучшения или исправления ошибок, которые могли бы быть применены к внутреннему UIButton
поведение.
UIButton
сам класс определяется для наследования от UIControl
, который описывает основное поведение, характерное для всех средств управления пользовательским интерфейсом на iOS. UIControl
класс поочередно наследовался от UIView
, предоставление его функциональность, характерная для объектов, выведенных на экран на экране. UIView
наследовался от UIResponder
, позволяя ему реагировать на ввод данных пользователем, такой как касания, жесты или встряски. Наконец, в корне дерева, UIResponder
наследовался от NSObject
, как показано на рисунке 1-3.
Эта цепочка наследования означает что любой пользовательский подкласс UIButton
наследовал бы не только функциональность, объявленную UIButton
самостоятельно, но также и функциональность наследовалась от каждого суперкласса поочередно. Вы закончили бы с классом для объекта, который вел себя как кнопка, мог вывести на экран себя на экране, реагировать на ввод данных пользователем и связаться с любым другим основным Сенсорным объектом Какао.
Важно помнить цепочку наследования для любого класса, который необходимо использовать для разработки точно, что это может сделать. Документация ссылки класса предусмотрела Касание Какао и Какао, например, позволяет простую навигацию от любого класса до каждого из его суперклассов. Если Вы не можете найти то, что Вы ищете в одном интерфейсе класса или ссылке, он может быть определен или задокументирован в суперкласс далее цепочка.
Интерфейс для класса определяет ожидаемые взаимодействия
Одно из многих преимуществ объектно-ориентированного программирования является идеей, упомянул ранее — все, что необходимо знать для использования класса, то, как взаимодействовать с его экземплярами. Более в частности объект должен быть разработан для сокрытия подробных данных его внутренней реализации.
Если Вы используете стандарт UIButton
в приложении для iOS, например, Вы не должны волноваться о том, как пикселями управляют так, чтобы кнопка появилась на экране. Все, что необходимо знать, - то, что можно изменить определенные атрибуты, такие как заголовок и цвет кнопки, и положить, что, когда Вы добавляете его к своему визуальному интерфейсу, это будет выведено на экран правильно и вести себя в способе, которым Вы ожидаете.
При определении собственного класса необходимо запустить путем выяснения этих общедоступных атрибутов и способов поведения. Какие атрибуты Вы хотите быть доступными публично? Необходимо ли позволить тем атрибутам быть измененными? Как другие объекты связываются с экземплярами Вашего класса?
Эта информация входит в интерфейс для Вашего класса — это определяет способ, которым Вы предназначаете другие объекты взаимодействовать с экземплярами Вашего класса. Открытый интерфейс описан отдельно от внутреннего поведения Вашего класса, составляющего реализацию класса. В Objective C интерфейс и реализация обычно помещаются в отдельные файлы так, чтобы Вы только обнародовали интерфейс.
Базовый синтаксис
Синтаксис Objective C, используемый для объявления интерфейса класса, похож на это:
@interface SimpleClass : NSObject |
@end |
Этот пример объявляет названный класс SimpleClass
, который наследовался от NSObject
.
Общедоступные свойства и поведение определяются в @interface
объявление. В этом примере ничто не указано вне суперкласса, таким образом, единственная функциональность ожидала быть доступной на экземплярах SimpleClass
функциональность, наследованная от NSObject
.
Доступ управления свойствами к значениям объекта
Объектам часто предназначали свойства для открытого доступа. При определении класса для представления человека в приложении ведения записей, например, Вы могли бы решить необходимость в свойствах для строк, представляющих имя и фамилию лица.
Объявления для этих свойств должны быть добавлены в интерфейсе, как это:
@interface Person : NSObject |
@property NSString *firstName; |
@property NSString *lastName; |
@end |
В этом примере, Person
класс объявляет два общедоступных свойства, оба из которых являются экземплярами NSString
класс.
Оба этих свойства для объектов Objective C, таким образом, они используют звездочку, чтобы указать, что они - указатели C. Они - также операторы точно так же, как любое другое объявление переменной в C, и поэтому требуют точки с запятой в конце.
Вы могли бы решить добавить свойство для представления года лица рождения, чтобы разрешить Вас людям вида в группах года, а не просто по имени. Вы могли использовать свойство для объекта числа:
@property NSNumber *yearOfBirth; |
но это можно было бы считать излишеством только для хранения простого числового значения. Одна альтернатива должна была бы использовать одни из типов примитивов, предоставленных C, содержащими скалярные значения, такие как целое число:
@property int yearOfBirth; |
Атрибуты свойства указывают соображения доступности и хранения данных
Примеры, показанные до сих пор, все объявляют свойства, предназначающиеся для полного открытого доступа. Это означает, что другие объекты могут и считать и изменить значения свойств.
В некоторых случаях Вы могли бы решить объявить, что свойство не предназначается, чтобы быть измененным. В реальном мире лицо должно заполнить большую сумму документов для изменения их задокументированного имени или фамилии. Если бы Вы писали официальное приложение ведения записей, то Вы могли бы выбрать это, общедоступные свойства для имени лица указаны как только для чтения, требуя, чтобы любые изменения требовали через посреднический объект, ответственный за проверку запроса и утверждение или отклонение его.
Объявления свойства Objective-C могут включать атрибуты свойства, использующиеся для указания, среди прочего, предназначается ли свойство, чтобы быть только для чтения. В официальном приложении ведения записей интерфейс класса Лица мог бы быть похожим на это:
@interface Person : NSObject |
@property (readonly) NSString *firstName; |
@property (readonly) NSString *lastName; |
@end |
Атрибуты свойства указаны в круглых скобках после @property
ключевое слово, и описано полностью в, Объявляют Общедоступные Свойства для Представленных Данных.
Объявления метода указывают сообщения, которые может получить объект
Примеры до сих пор включили класс, описывающий типичный объект модели или объект, разработанный прежде всего для инкапсуляции данных. В случае a Person
класс, возможно, что не должно было бы быть никакой функциональности вне способности получить доступ к двум заявленным свойствам. Большинство классов, однако, действительно включает поведение в дополнение к любым заявленным свойствам.
Учитывая, что программное обеспечение Objective-C создается из большой сети объектов, важно отметить, что те объекты могут взаимодействовать друг с другом путем отправки сообщений. В условиях Objective C один объект отправляет сообщение в другой объект путем вызова метода на том объекте.
Методы Objective C концептуально подобны стандартным функциям в C и других языках программирования, хотя синтаксис очень отличается. Объявление функции C похоже на это:
void SomeFunction(); |
Эквивалентное объявление метода Objective C похоже на это:
- (void)someMethod; |
В этом случае метод не имеет никаких параметров. C void
ключевое слово используется в круглых скобках в начале объявления, чтобы указать, что метод не возвращает значения, как только это закончено.
Знак «минус» (-
) впереди имени метода указывает, что это - метод экземпляра, который можно вызвать на любом экземпляре класса. Это дифференцирует его от методов класса, которые можно вызвать на самом классе, как описано в Objective C, Классы Являются также Объектами.
Как с прототипами функции C, объявление метода в интерфейсе класса Objective C точно так же, как любой другой оператор C и требует завершающейся точки с запятой.
Методы могут взять параметры
Если необходимо объявить, что метод берет один или несколько параметров, синтаксис очень отличается от типичной функции C.
Для функции C параметры указаны в круглых скобках, как это:
void SomeFunction(SomeType value); |
Объявление метода Objective C включает параметры как часть его имени, с помощью двоеточий, как это:
- (void)someMethodWithValue:(SomeType)value; |
Как с типом возврата, тип параметра указан в круглых скобках, точно так же, как стандарт C преобразование типа.
Если необходимо предоставить многократные параметры, синтаксис снова очень отличается от C. Многократные параметры к функции C указаны в круглых скобках, разделенных запятыми; в Objective C объявление для метода, берущего два параметра, похоже на это:
- (void)someMethodWithFirstValue:(SomeType)value1 secondValue:(AnotherType)value2; |
В этом примере, value1
и value2
имена, используемые в реализации для доступа к значениям, предоставленным, когда метод вызывают, как будто они были переменными.
Некоторые языки программирования позволяют функциональные определения с так называемыми параметрами, передаваемыми по имени; важно отметить это дело обстоит не так в Objective C. Порядок параметров в вызове метода должен соответствовать объявление метода, и фактически secondValue:
часть объявления метода является частью имени метода:
someMethodWithFirstValue:secondValue: |
Это - одна из функций, помогающая сделать Objective C таким читаемым языком, потому что значения, переданные вызовом метода, указаны встроенные, рядом с соответствующей частью имени метода, как описано в Вас Может Передать Объекты для Параметров Метода.
Имена классов должны быть уникальными
Важно отметить, что имя каждого класса должно быть уникальным в приложении, даже через включенные библиотеки или платформы. При попытке создать новый класс с тем же именем как существующий класс в проекте, то Вы получите ошибку компилятора.
Поэтому желательно снабдить префиксом имена любых классов, которые Вы определяете, с помощью трех или больше букв. Эти буквы могли бы коснуться приложения, которое Вы в настоящее время пишете, или в имя платформы повторно используемого кода, или возможно просто Ваши инициалы.
Все примеры, данные в остальной части этого документа, используют префиксы имени класса, как это:
@interface XYZPerson : NSObject |
@property (readonly) NSString *firstName; |
@property (readonly) NSString *lastName; |
@end |
Метод и имена свойства, в отличие от этого, должны только быть уникальными в классе, в котором они определяются. Несмотря на то, что каждая функция C в приложении должна иметь уникальное имя, это совершенно приемлемо (и часто желательно) для многократных классов Objective C для определения методов с помощью того же имени. Вы не можете определить метод несколько раз в том же объявлении класса, однако, хотя, если Вы хотите переопределить метод, наследованный от родительского класса, необходимо использовать точное имя, используемое в исходном объявлении.
Как с методами, свойства объекта и переменные экземпляра (описанный в Большинстве Свойств Поддерживаются Переменными экземпляра) должны быть уникальными только в классе, в котором они определяются. При использовании глобальных переменных, однако, их нужно назвать уникально в приложении или проекте.
Дальнейшие соглашения о присвоении имен и предложения даны в Соглашениях.
Реализация класса обеспечивает свое внутреннее поведение
Как только Вы определили интерфейс для класса, включая свойства и методы, предназначенные для открытого доступа, необходимо записать код для реализации поведения класса.
Как утверждено ранее, интерфейс для класса обычно помещается в специализированном файле, часто называемом заголовочным файлом, обычно имеющим расширение файла .h
. Вы пишете реализацию для класса Objective C в файле исходного кода с расширением .m
.
Каждый раз, когда интерфейс определяется в заголовочном файле, необходимо будет сказать компилятору читать его прежде, чем попытаться скомпилировать реализацию в файле исходного кода. Objective C обеспечивает директиву препроцессору, #import
, с этой целью. Это подобно C #include
директива, но удостоверяется, что файл только включен один раз во время компиляции.
Обратите внимание на то, что директивы препроцессору отличаются от традиционных операторов C и не используют завершающуюся точку с запятой.
Базовый синтаксис
Базовый синтаксис для обеспечения реализации для класса похож на это:
#import "XYZPerson.h" |
@implementation XYZPerson |
@end |
Если Вы объявите какие-либо методы в интерфейсе класса, то необходимо будет реализовать их в этом файле.
Реализация методов
Поскольку простой класс взаимодействует через интерфейс с одним методом, как это:
@interface XYZPerson : NSObject |
- (void)sayHello; |
@end |
реализация могла бы быть похожей на это:
#import "XYZPerson.h" |
@implementation XYZPerson |
- (void)sayHello { |
NSLog(@"Hello, World!"); |
} |
@end |
Этот пример использует NSLog()
функционируйте для журналирования сообщения к консоли. Это подобно стандартной библиотеке для C printf()
функция, и берет переменное число параметров, первым из которых должна быть строка Objective C.
Реализации метода подобны определениям функции C, в которых они используют фигурные скобки для содержания соответствующего кода. Кроме того, имя метода должно быть идентично его прототипу, и параметр и типы возврата должны соответствовать точно.
Objective C наследовал чувствительность к регистру от C, таким образом, этот метод:
- (void)sayhello { |
} |
был бы обработан компилятором как абсолютно отличающийся от sayHello
метод, показанный ранее.
В целом имена методов должны начаться со строчной буквы. Соглашение Objective C состоит в том, чтобы использовать более описательные имена для методов, чем Вы могли бы видеть используемый для типичных функций C. Если имя метода включает многократные слова, используйте Camel-регистр (капитализирующий первую букву каждого нового слова) для создания их простыми читать.
Отметьте также, что пробел гибок в Objective C. Это обычно для расположения с отступом каждой строки в любом блоке кода с помощью или вкладок или пробелов, и Вы будете часто видеть вводную левую фигурную скобку на отдельной строке, как это:
- (void)sayHello |
{ |
NSLog(@"Hello, World!"); |
} |
XCode, интегрированная среда разработки (IDE) Apple для создания OS X и программного обеспечения iOS, автоматически расположит Ваш код с отступом на основе ряда настраиваемых пользовательских настроек. Посмотрите Изменение Отступа и Вкладки Width в Руководстве по Рабочей области XCode для получения дополнительной информации.
Вы будете видеть еще много примеров реализаций метода в следующей главе, Работающей с Объектами.
Классы Objective C Являются также Объектами
В Objective C класс является самостоятельно объектом с непрозрачным вызванным типом Class
. Классы не могут иметь определенного использования свойств синтаксиса объявления, показанного ранее для экземпляров, но они могут получить сообщения.
Типичное использование для метода класса как метод фабрики, который является альтернативой объектному выделению, и процедура инициализации, описанная в Объектах, Создаются Динамично. NSString
класс, например, имеет множество методов фабрики, доступных для создания или объекта пустой строки или строкового объекта, инициализированного с определенными символами, включая:
+ (id)string; |
+ (id)stringWithString:(NSString *)aString; |
+ (id)stringWithFormat:(NSString *)format, …; |
+ (id)stringWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error; |
+ (id)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc; |
Как показано в этих примерах, методы класса обозначены при помощи a +
знак, дифференцирующий их от методов экземпляра с помощью a -
знак.
Прототипы метода класса могут быть включены в интерфейс класса, точно так же, как прототипы метода экземпляра. Методы класса реализованы таким же образом как методы экземпляра, в @implementation
блок для класса.
Упражнения
Используйте окно шаблона New File XCode для создания интерфейса и файлов реализации для вызванного класса Objective C
XYZPerson
, который наследовался отNSObject
.Добавьте свойства для имени лица, фамилия и дата рождения (даты представлены
NSDate
класс) кXYZPerson
интерфейс класса.Объявите
sayHello
метод и реализация это как показано ранее в главе.Добавьте объявление для метода фабрики классов, вызванного “
person
”. Не волнуйтесь о реализации этого метода, пока Вы не считали следующую главу.