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