14 февр. 2014 г.

@property свойства класса


Ключевое слово @property позволяет объявить свойства класса в языке Objective C. По своей сути свойства являются средством написания кода, позволяющим удобно обращаться к полям класса, не нарушая принципа инкапсуляции и не используя синтаксис вызова методов. Свойства не обязательно должны базироваться на полях класса. Они могут, например, вычисляться во время каждого вызова. Основной смысл использования свойств – более удобный синтаксис в сравнении с обычными вызовами методов. Возможность использовать свойства появилась в языке Objective C начиная с версии 2.0. Для лучшего понимания принципов работы свойств рассмотрим несколько примеров. Предположим, у нас есть класс Car, содержащий поле speed для хранения скорости автомобиля. Тогда объявление этого класса будет выглядеть так:
@interface Car : NSObject
{
double speed;
}
-(double) getSpeed;
-(void) setSpeed:(double)s;
@end
Сообщения getSpeed и setSpeed позволяют читать и изменять закрытое поле speed, реализовывая принцип инкапсуляции. Реализация данного класса может выглядеть следующим образом:
@implementation Car
-(void) setSpeed:(double)s
{
if ( s>=0 )
{
speed = s;
}
}
-(double) getSpeed
{
return speed;
}
@end
Создание экземпляра этого класса и использование поля могут быть такими:
Car *car = [[Car alloc] init];
[car setSpeed:105];
NSLog(@"%f", [car getSpeed]);
[car release];
На приведенном выше примере можно увидеть, что чтение значений из полей класса и занесение новых значений синтаксически не очень удобно. Гораздо удобнее было бы напрямую обратиться к полям класса при помощи оператора -> Но тогда поля класса пришлось бы сделать открытыми и было бы невозможно контролировать значения, заносимые в поля. Применение свойств как раз и должно решить эту проблему. С использованием ключевого слова @property объявление класса примет такой вид:
@interface Car : NSObject{ double speed;} @property double speed; @end
Как видно из примера, при объявлении свойства указывается тип свойства и в данном случае он совпадает с типом поля класса. Так же Objective C допускает одинаковые названия свойств и полей классов. С учётом сделанных изменений, реализация класса будет такой:
@implementation Car
@synthesize speed;
@end
Упрощение кода в данном случае заметить не трудно. Мы просто убрали реализацию методов доступа к полю speed и заменили её на автоматическую генерацию поля при помощи ключевого слова @synthesize. Теперь попробуем воспользоваться созданным свойством:
Car *car = [[Car alloc] init];
car.speed = 45.5;
NSLog(@"%f", car.speed);
[car release];
Вот ради чего всё затевалось. Теперь мы можем обращаться к полю класса при помощи удобного оператора “точка”. В этом и есть основной смысл свойств. Но в этом коде всё ещё есть проблемы. Дело в том, что в поле speed можно запросто занести отрицательные значения. И данное автоматически сгенерированное свойство никак не может этому помешать. Такая реализация свойства не очень-то и полезна для класса Car. Поэтому переделаем реализацию, добавив в неё аксессоры для доступа к полю.
@implementation Car
-(void) setSpeed:(double)s
{
if(s>0) speed = s;
}
-(double) speed
{
return speed;
}
@end
Теперь свойство не позволит заносить в поле класса отрицательные значения. Несмотря на то, что кода стало больше, свойство защищает поле класса от некорректных значений. На примере можно увидеть, что имя метода, возвращающего значение, совпадает с именем свойства, а имя метода, записывающего новые значения почучается добавлением слова set в начало имени метода, название свойства начинается с большой буквы. В принципе, названия методов-аксессоров можно изменить. Для этого придётся внести изменения в объявление свойства:
@interface Car : NSObject
{
double speed;
}
@property (getter = getSpeed, setter = setSpeed:) double speed;
@end
После таких изменений объявления свойства метод, возвращающий значение свойства должен называться getSpeed, а метод задающий значение свойства, должен называться setSpeed.

0 коментарі:

Отправить комментарий