Чтение онлайн

на главную - закладки

Жанры

Программирование на Objective-C 2.0
Шрифт:

[dataArray2 release]; ## 18.2. Поверхностное и глубокое копирование В программе 18.1 элементы массива dataArray заполняются немутабельными стро-ками (напомним, что константные строковые объекты яатяютси немутабельными). В программе 18.2 мы будем заполнять его мутабельными строками, чтобы можно было изменить одну из арок в этом массиве. Просмотрите программу 18.2 и постарайтесь понять ее вывод. import ffimport import import

int main (int arge, char argv[]) { NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init]; NSMutableArray dataArray = [NSMutableArray arrayWithObjects: [NSMutableString stringWithString: @"one"], [NSMutableString stringWithString: @"two"], [NSMutableString stringWithString: @"three"], nil ]; NSMutableArray dataArray2; NSMutableString mStr; NSLog (@"dataArray:"); for ( NSString elem in dataArray ) NSLog {@" %@", elem); // создание копии, затем изменение одной из строк dataArray2 = [dataArray mutableCopy]; mStr = [dataArray objectAtlndex: 0]; [mStr appendString: @"ONE"]; NSLog (@"dataArray: for ( NSString elem in dataArray ) NSLog (@" %@", elem); NSLog (@"dataArray2: "); for ( NSString e!em in dataArray2 ) NSLog (@" %@", elem); [dataArray2 release]; [pool drain]; return 0; } Вывод программы 18.2

dataArray: one two three dataArray: oneONE two three dataArray2: oneONE two three `` Мы считываем первый элемент массива dataArray с помощью оператора mStr = [dataArray objectAtlndex: 0]; и добавляем в него строку' @"ONE" с помощью оператора [mStr appendString: @"ONE"];

Обратите внимание на значение первого элемента исходного массива и его копии: в обоих массивах оно было изменено. Понятно, почему был изменен первый элемент dataArray, но почему была изменена и его копия? Получая элемент из коллекции, мы получаем новую ссылку на этот элемент, но не новую копию. Поэтому при вызове метода objectAtlndex: для dataArray возвращаемый объект указывает на тот же объект в памяти, что и первый элемент в dataArray. Последующее изменение строкового объекта mStr также сопровождается изменением первого элемента массива dataArray, что подтверждается результатами вывода.

Но почему изменился первый элемент созданной копии? По умолчанию копии ивляклси поверхностными (shallow) копиями. Когда массив был скопирован с помощью метода mutableCopy, в памяти было выделено пространство для нового объекта-массива, и элементы были скопированы в новый массив. Но копирование каждого элемента массива из исходного места в новое означает только копирование ссылки из одного элемента массива в другой. В результате элементы обоих массивов ссылаются на одни и те же строки в памяти, что не отличается от присваивания одного объекта другому, о котором мы говорили в начале этой главы.

Чтобы создать другие копии каждого элемента массива, необходимо выпол-нить глубокое (deep) копирование, при котором создаются копии содержимого каждого объекта в массиве, а не копируются ссылки на объекты (подумайте, что это означает, если элемент массива сам является объектом-массивом). Но глубокое копирование не выполняется по умолчанию, если мы используем методы сору или mutableCopy с классами Foundation. В главе 19 мы покажем возможности архивации Foundation для создания глубокой копии объекта.

Копируя массив, словарь или набор, мы получаем новую копию этих кол-лекций. Создание копий отдельных элементов может потребоваться, например, если нужно внести изменения в коллекцию, но не в ее копию. Например, если в программе 18.2 нужно было бы изменить первый элемент массива dataAnay2, но не dataArray, вы могли бы создать новую строку (например, с помощью ме тода stringWithString:) и сохранить ее в первом элементе dataArray2 с помощью оператора mStr = [NSMutableString stringWithString: [dataArray2 objectAtlndex: 0]];

Затем можно было бы внести изменения в переменную mStr и добавить ее в этот массив с помощью метода replaceObject: at I ndex:withObject: [mStr appendString @"ONE"]; [dataArray2 replaceObjectAtlndex: 0 withObject: mStr];

Даже после замены объекта mStr и первый элемент dataArray2 ссылаются на один и тот же объект в памяти. Поэтому последующее изменение в mStr вызовет также изменение первого элемента э того массива. Чтиобы избежать этого, выс-вободите (release) mStr и выделите память (alloc) для нового экземпляра, поскольку метод replaceObject:allndex:withObject: автоматически удерживает объект. 18.3. Реализация протокола

Если применить метод сору к одному из ваших собственных классов, например, к вашей адресной книге (address book), как в строке NewBook = [myBook mutableCopy];

то будет выдано сообщение об ошибке: *** -[AddressBook copyWithZone:]: selector not recognized (селектор не распознан) *** Uncaught exception: (Невыявленное исключение) *** -[AddressBook copyWithZone:]: selector not recognized

Как уже говорилось, для реализации копирования с вашими собственными классами необходимо реализовать один или два метода согласно протоколу .

Теперь покажем, как добавить метод сору в класс Fraction, который много ис-пользовался в части I. Эти способы вполне применимы для ваших собственных классов. Если эти классы являются подклассами любого из классов Foundation, то потребуется реализация более сложной стратегии копирования, поскольку' в суперклассе может быть уже реализована его собственная стратегия копирования.

Напомним, что класс Fraction содержит две целые переменные экземпляра: numerator (числитель) и denominator (знаменатель). Чтобы создать копию одного из этих объектов, необходимо выделить пространство для новой дроби (fraction) и затем скопировать значения этих переменных в эту новую дробь.

При реализации протокола ваш класс должен реализовать метод copyWithZone:, чтобы реагировать на сообщение сору. (Сообщение сору просто передает сообщение copyWithZone: в наш класс с аргументом nil.) Если вам нужно отличать мутабельные и немутабельные копии, то потребуется также реализовать метод mutaЫеСоpyWithZone: согласно протоколу . Если вы реализуете оба метода, то copyWithZone: будет возвращать немугабельную копию, a mutableCopyWithZone: будет возвращать мутабельную копию. Создание мутабель- кой копии объекта не требует, чтобы копируемый объект был тоже мутабель- ным, и наоборот; вполне возможно, что может требоваться мутабельная копия немутабельного объекта (например, строкового объекта).

Директива @interface должна выглядеть следующим образом. @interface Fraction: NSObject <NSCopying>

Fraction — это подкласс NSObject, подчиняющийся протоколу NSCopying.

В файле секции implementation Fraction.m добавьте следующее определение для нового метода. -(id) copyWithZone: (NSZone *) zone { Fraction *newFract = [(Fraction allocWithZone: zone] init]; [newFract setTo: numerator over: denominator]; return newFract; }

Аргумент zone применяется для разных зон памяти, которые вы можете вы-делить для работы с профаммой. Это требуется только в том случае, если ваши приложения занимают много памяти, и вы хотите оптимизировать выделение памяти, группируя ее по зонам. Вы можете брать значение, передаваемое методу copyWithZone:, и передавать его методу выделения памяти allocWithZone:. Этот метод выделяет память в указанной зоне.

Поделиться:
Популярные книги

Бояръ-Аниме. Газлайтер. Том 30

Володин Григорий Григорьевич
30. История Телепата
Фантастика:
альтернативная история
аниме
фэнтези
5.00
рейтинг книги
Бояръ-Аниме. Газлайтер. Том 30

На границе империй. Том 9. Часть 4

INDIGO
17. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 4

Войны Наследников

Тарс Элиан
9. Десять Принцев Российской Империи
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Войны Наследников

Кодекс Охотника. Книга XXII

Винокуров Юрий
22. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXII

Помещик

Беличенко Константин
1. Помещик
Фантастика:
боевая фантастика
попаданцы
5.56
рейтинг книги
Помещик

Звездная Кровь. Изгой V

Елисеев Алексей Станиславович
5. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
попаданцы
технофэнтези
рпг
фантастика: прочее
5.00
рейтинг книги
Звездная Кровь. Изгой V

Кодекс Охотника XXXI

Винокуров Юрий
31. Кодекс Охотника
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Охотника XXXI

Сильнейший Столп Империи. Книга 2

Ермоленков Алексей
2. Сильнейший Столп Империи
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Сильнейший Столп Империи. Книга 2

Архил...? 4

Кожевников Павел
4. Архил...?
Фантастика:
фэнтези
попаданцы
альтернативная история
5.50
рейтинг книги
Архил...? 4

Древесный маг Орловского княжества

Павлов Игорь Васильевич
1. Орловское княжество
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Древесный маг Орловского княжества

На границе империй. Том 7

INDIGO
7. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
6.75
рейтинг книги
На границе империй. Том 7

Московское золото и нежная попа комсомолки. Часть Пятая

Хренов Алексей
5. Летчик Леха
Фантастика:
попаданцы
5.00
рейтинг книги
Московское золото и нежная попа комсомолки. Часть Пятая

Третий Генерал: Том IV

Зот Бакалавр
3. Третий Генерал
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Третий Генерал: Том IV

Контртеррор

Валериев Игорь
6. Ермак
Фантастика:
альтернативная история
5.00
рейтинг книги
Контртеррор