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

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

Жанры

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

Мы часто используем этот стиль в книге, поэтому важно, чтобы вы понимали его. Вы видели выше, как действует автоматически высвобождаемый пул (autorelease pool): NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

Здесь сообщение alloc отправляется классу NSAutoreleasePool для запроса о создании нового экземпляра. Затем этому новому созданному объекту отправ-ляется сообщение init для его инициализации.Теперь, вернувшись к программе 3.2, вы можете задать значение дроби. // Set fraction to 1/3 [myFraction setNumerator: 1]; [myFraction setDenominator: 3];

В первом операторе выполняется отправка сообщения setNumerator: переменной myFraction. Для аргумента указывается значение 1, и управление передается методу setNumerator:, который был определен для класса Fraction. Система Objective - С «понимает», что это метод изданного класса, поскольку «знает», что myFraction является объектом из класса Fraction.

Внутри метода setNumerator: переданное значение 1 сохраняется в перемен-ной п. В единственной программной строке метода это значение сохраняется в переменной экземпляра numerator. Фактически вы присваиваете элементу numerator в myFraction значение 1.

Затем следует сообщение для обращения к методу setDenominator: в myFraction. Значение аргумента 3 присваивается переменной d внутри метода setDenominator:. Это значение затем сохраняется в переменной экземпляра denominator, что завершает присваивание значения 1/3 переменной myFraction. Теперь можно вывести на экран значение дроби. // display the fraction using the print method NSLog (@The value of myFraction is:"); [myFraction print];

В результате вызова NSLog выводится текст: The value of myFraction is: (Значение myFraction:)

В следующем выражении для сообщения вызывается метод print: [myFraction print];

Внутри метода print выполняется вывод значений переменных экземпляра numerator и denominator, разделенных наклонной чертой.

Следующее сообщение в программе освобождает память, которая исполь-зовалась для этого объекта Fraction: [myFraction release];

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

В системе выполнения программ (runtime) Apple обеспечивается механизм очистки памяти, который называется сборкой мусора (garbage collection), но луч-ше самому управлять использованием памяти, а не полагаться на этот автома-тизированный механизм.

Вы не можете полагаться на сборку мусора для тех платформ, где она не поддерживается, например, iPhone. У вас может создаться впечатление, что вам пришлось написать намного больше кода, чтобы сделать в программе 3.2 то же самое, что и в программе 3.1. Для данного простого примера это верно, но такой способ делает упрощает написание, поддержку и расширение больших и сложных программ. Вы поймете это позже.

В последнем примере этой главы показано, как работать с несколькими дро-бями. В программе 3.3 одной дроби присваивается значение 2/3, второй дроби — 3/7, и затем выполняется вывод обеих дробей. // Program to work with fractions - cont’d (Программа для работы с дробями - продолжение) #import <Foundation/Foundation.h> //---- @interface section ---- @interface Fraction: NSObject { int numerator; int denominator; } -(void) print; -(void) setNumerator: (int) n; -(void) setDenominator: (int) d; @end //---- @implementation section ---- @implementation Fraction -(void) print { NSLog (@"%i/%i", numerator, denominator); } -(void) setNumerator: (int) n { numerator = n; ) -(void) setDenominator: (int) d { denominator = d; } @end //---- program section ---- int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Fraction *frac1 = [[Fraction alloc] init]; Fraction *frac2 = [[Fraction alloc] init]; // Set 1st fraction to 2/3 (Задание 1 -й дроби 2/3) [frac setNumerator: 2]; [frac setDenominator: 3]; // Set 2nd fraction to 3/7 (Задание 2-й дроби 3/7) [frac2 setNumerator: 3]; [frac2 setDenominator: 7]; // Display the fractions (Вывод дробей) NSLog (@"First fraction is:"); [frac print]; NSLog (@"Second fraction is:"); [frac2 print]; [frac release]; [frac2 release]; [pool drain]; return 0; }

Вывод программы 3.3 First fraction is: (Первая дробь:) 2/3 Second fraction is: (Вторая дробь:) 3/7

Секции @interface и @implementation остались такими же, как в программе 3.2. В программе создаются два объекта типа Fraction, — frad и frac2, затем им присва-иваются соответственно значения 2/3 и 3/7. Когда метод setNumerator: применяется к frad, чтобы задать значение 2 для его числителя (numerator), выполняется присваивание значения 2 переменной экземпляра numerator. Аналогичным об-разом, когда для frac2 применяется тот же метод, чтобы задать значение 3 для его числителя, выполняется присваивание значения 3 его отдельной переменной экземпляра numerator. Новый объект получает свой собственный отдельный набор переменных экземпляра при каждом создании (рис. 3.2).

В зависимости от объекта, которому отправляется сообщение, происходит ссылка на соответствующие переменные экземпляра. В следующем примере выполняется ссылка на numerator объекта fraci, если внутри метода setNumerator: используется имя numerator: [trad setNumerator: 2];

Это происходит потому, что получателем сообщения является frac1.

Рис. 3.2. Уникальные переменные экземпляра 3.7. Доступ к переменным экземпляра и инкапсуляция данных

Мы увидели, каким образом методы, используемые для работы с дробями, вы-полняют доступ по имени к двум переменным экземпляра: numerator и denominator. Метод экземпляра всегда может выполнять непосредственный доступ к переменным экземпляра. Однако это не может делать метод класса, поскольку он применяется только к самому классу, а не к экземплярам этого класса. Но что делать, если нужно выполнять доступ к переменным экземпляра из какого-либо другого места, например, изнутри процедуры main? Это нельзя сделать напрямую, поскольку переменные экземпляра скрыты. Это еще одна ключевая концепция, которая называется инкапсуляцией данных (data encapsulation). Это позволяет расширять и изменять определения класса, не заботясь о том, что пользователи данного класса будут работать с внутренними деталями класса. Инкапсуляция данных обеспечивает необходимый уровень изоляции между программистом и разработчиком класса.

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

Их определения: -(int) numerator { return numerator; } -(int) denominator { return denominator; }

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

Сирота

Ланцов Михаил Алексеевич
1. Помещик
Фантастика:
альтернативная история
5.71
рейтинг книги
Сирота

Лекарь Империи 3

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

Сын ведьмы. Дилогия

Седых Александр Иванович
Сын ведьмы
Фантастика:
боевая фантастика
альтернативная история
6.15
рейтинг книги
Сын ведьмы. Дилогия

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

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

Кодекс Императора

Сапфир Олег
1. Кодекс Императора
Фантастика:
аниме
фэнтези
попаданцы
4.25
рейтинг книги
Кодекс Императора

Тринадцатый VI

NikL
6. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Тринадцатый VI

Газлайтер. Том 1

Володин Григорий
1. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 1

Эпоха Опустошителя. Том IV

Павлов Вел
4. Вечное Ристалище
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Эпоха Опустошителя. Том IV

Агенты ВКС

Вайс Александр
3. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Агенты ВКС

Бастард Императора

Орлов Андрей Юрьевич
1. Бастард Императора
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Бастард Императора

Шайтан Иван 4

Тен Эдуард
4. Шайтан Иван
Фантастика:
попаданцы
альтернативная история
8.00
рейтинг книги
Шайтан Иван 4

Личный аптекарь императора. Том 4

Карелин Сергей Витальевич
4. Личный аптекарь императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Личный аптекарь императора. Том 4

Я не царь. Книга XXIV

Дрейк Сириус
24. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я не царь. Книга XXIV

Двойник короля 16

Скабер Артемий
16. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 16