Начинающие программировать под iOS испытывают определенные трудности, применяя пары изменяемых и неизменяемых классов из каркаса Foundation, поэтому здесь уместно дать некоторые рекомендации по этому поводу.

Из документации может быть не совсем ясно, что в изменяемых классах исполняются, а по возможности и замещаются, методы из неизменяемых классов. Так, выражение [NSArray array] формирует неизменяемый массив, тогда как выражение [NSMutableArray array] — изменяемый массив. Это же справедливо и для получения экземпляров с помощью всех инициализаторов и методов служебных классов. Они могут включать в свои имена слово "array", но при отправке классу NSMutableArray они предоставляют изменяемый массив.

Это обстоятельство дает также ответ на следующий вопрос: как сделать неизменяемый массив изменяемым, и наоборот? Если метод arrayWithArray: посылается классу NSArray, то он предоставляет изменяемый массив, содержащий те же самые объекты в том же порядке, что и в оригинале. Следовательно, этот единственный метод может преобразовать неизменяемый массив в изменяемый, и обратно. С помощью метода сору можно также получить неизменяемую копию, а с помощью метода mutableCopy — изменяемую.

Все сказанное выше в равной степени относится и к парам изменяемых и неизменяемых классов. Часто удобно автоматически работать с временным изменяемым экземпляром, а затем сохранять (а возможно, и поставлять другим классам) неизменяемый экземпляр, защищая тем самым значение от случайного изменения или без вашего ведома. Дело не в том, как объявлен класс, к которому относится переменная, а в том, к какому классу на самом деле относится экземпляр (полиморфизм; см. главу 5). Следовательно, возможность легко переходить от неизменяемого к изменяемому варианту одних и тех же данных является благом.

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

 

if ([NSStringFromClass{[n class]) isEqualToString: @"NSCFArray"]) // неверно!

 

Вместо этого выяснить, является ли коллекция изменяемой, можно, проверив, реагирует ли она на модифицирующий метод:

 

if ([n respondsToSelector:0selector(addObject:)]) // верно!

 

(К сожалению, такой прием годится только для коллекций. Он не подходит, например, для того, чтобы отличить класс NSString от класса NSMutableString.)

 

 

Если класс коллекции является неизменяемым, это совсем не означает, что объекты, собранные в его коллекции, также являются неизменяемыми. Они по-прежнему остаются объектами и не теряют свое обычное поведение лишь потому, что они указываются посредством неизменяемой коллекции.


 

 

 

Добавить комментарий