Синтаксис языка

Objective-C

Первое, что мы встречаем это директиву #import - действие ее аналогично директиве #include языка С, с тем лишь отличием, что допускает множественные включения в код без использования конструкций директив #ifdef, без боязни рекурсивного включения одного и того-же файла. Но никто не запрещает Вам использовать #include, хотя врядли это будет удобным.

Для обозначения объектов используется специальный тип id. Переменная типа id фактически является указателем на произвольный объект. Для обозначения нулевого указателя на объект используется константа nil.

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

Для посылки сообщений используется следующий синтаксис:


 [receiver message];

receiver - указатель на объект

message - имя метода

(Немного похоже на С++ конструкцию указатель->метод).

Все директивы, используемые Objective-C начинаются с символа @

Классы

Для объявления класса создается в заголовочном файле с расширением .h и использует синтаксис:


@interface имя_класса : super_Class
{
  объявление переменных; (имеют зону видимости private) 
}
  объявление методов;
@end

Реализация класса создается в файле с расшерением .m и использует синтаксис:


#import "имя_класса.h"
@implementation имя_класса

  реализация методов;

@end

Пример:

mac os x .h Файл first.h

#import <Cocoa/Cocoa.h>
@interface first : NSObject
{
  int a;
  int b;
}
- (id)init;
- (void)setA :(int)A andB :(int)B;
- (long)summa;
- (long)mul;
@end

Здесь мы видим объявление класса с именем first порожденный от класса NSObject (В Apple runtime библиотеке все классы являются наследниками класса NSObject, если мы будем писать программы с использованием Cocoa, то будет хорошей практикой наследовать свои классы также от NSObject, предоставляющего множество полезных возможностей).

Директива #import подключает к нашему объявлению заголовок Cocoa.h, содержащий объявления всех классов и протоколов пространства Cocoa.framework.

Далее следует объявление переменных типа Integer a и b, следом идут методы, начинающиеся с символа - (иногда с +), далее в скобках указывается возвращаемый тип данных, следом название метода, далее аргументы через пробел, перед скобками с типом аргумента ставится двоеточие, перед аргументом может стоять метка (в методе setA - меткой аргумента B является слово andB - наследие Smalltalk), используется для большей читабельности кода.

mac os x .m Файл first.m

#import "first.h"
@implementation first
- (id)init {
  self = [super init];
  if(self){
    //инициализация вашего класса
  }
  return self;
}
- (void)setA :(int)A andB :(int)B{
  a = A;
  b = B;
}
- (long)summa{
  return a+b;
}
- (long)mul{
  return a*b;
}
@end

Начало файла реализации класса стандартно: с директивы #import "first.h", загружающей объявление класса.

Директива @implementation first говорит компилятору, что далее следует реализация класса first

Далее следует функция init, которая служит для инициализации нашего класса. При создании экземпляра класса после выделения памяти всегда необходимо инициализировать класс, метод init - это перегруженный метод наследуемого класса(Супер класса) NSObject, поэтому в самом начале мы вызываем метод init наследуемого класса, для определения которого зарезервировано слово super. Значение, возвращаемое инициализатором, является указателем на наш класс, если инициализация неудачна, то возвращаемое значение равно nil.

self - зарезервированный указатель, который указывает на наш класс внутри самого класса

Инициализатор можно и не перегружать, просто опустив его объявление и реализацию. Также класс может содержать несколько инициализаторов, также содержащих и аргументы.

Далее следует реализация методов, практически ничем не отличающаяся от обычного C

В вышеуказанном примере переменные a и b имеют зону видимости только внутри своего класса. Мы написали метод setA:(int) andB:(int) для установки их значений. Если же нам необходимо прочитать значение a или b, то необходимо написать методы возвращающие их.

Например:


- (int)valueA{
  return a;
}
Выглядит весьма запарно.

Свойства

Начиная с Objective C 2.0 появилось понятие - свойство, под свойство выделена директива @property, которая указывает, что данная переменная класса имеет метод для чтения и записи в нее. Данная директива объявляется в файле объявлении класса.

Сопутствующая директиве @property, директива говорящая компилятору, что необходимо создать методы для доступа к переменной носит наименование @synthesize и объявляется в файле реализации класса.

Синтаксис объявления свойства:>


@property (атрибуты, через запятую) тип имя;

Пример:

mac os x .h Файл myclass.h


@interface myclass
{
  int a;
  int b;
}
@property int a;
@property int b;

@end;

Как видим здесь объявляется класс myclass с двумя переменными a и b, доступными извне с помощью объявления свойств.

mac os x .m Файл myclass.m

#import "myclass.h"
@implementation myclass

@synthesize a;
@synthesize b;

@end

Вот так все стало проще. Теперь мы имеем для переменных методы, позволяющие считывать и записывать их значения.

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

Внимание. Начиная с Xcode 4.5 использование @synthesize в файле реализации стало необязательным. В этом случае в файле - заголовке объявляется свойство @property NSInteger a;, доступ к самой переменной будет начинаться с символа подчеркивания _a, а доступ к сеттеру или геттеру внутри класса [self a].

Атрибуты свойств

В случае необходимости можно переопределить методы установки или чтения переменной вместе называемые акцессорами (Accessor) и соответственно чтения - геттер (getter), записи - сеттер (setter):


getter=метод геттера
setter=метод сеттера

Бывает не всегда нужно предоставлять полный доступ к переменной класса, в этом случае нужно ограничить его в объявлении @property:

  • readwrite - и чтение и запись
  • readonly - только чтение

Свойство только для чтения будет выглядеть так: @property (readonly) int a;

Семантика сеттеров свойств

strong - обозначает строгое переназначение объекта, делая указатель на объект владельцем этого объекта

weak - в отличии от strong обозначает нестрогое соответствие и если объект был освобожден из памяти (из другого класса или потока), то значение установится в nil. Не поддерживается OS X v10.6 и iOS 4; используйте assign

copy - указывает на то, что для присваивания будет использована копия переданного объекта. Первоначальному объекту посылается сообщение release. Может быть использовано только для объектов, поддерживающих протокол NSCopying, например NSString.

assign - для задания нового значения используется оператор присваивания. Используется только для скалярных типов (NSInteger и CGRect) либо для объектов, которыми мы не владеем.

retain - укaзывает на тo, что для объекта, используемого в качестве нового значения instance-переменной, управление памятью происходит вручную (не забываем потом освободить память).

Atomic

nonatomic - делает более быстрым способ доступа к объекту в немногозадачной среде, так-как в случае с atomic (по умолчанию все акцессоры atomic) и использованием strong, copy, или retain, во избежание коллизий с возможностью доступа к свойству из других потоков в сеттере строится код блокирующий переключение между потоками.

 
 
homeЗаметили ошибкукарта сайта 
   Made on a Mac