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

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

Жанры

Программирование на 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.00
рейтинг книги
Рунный маг Системы

Надуй щеки!

Вишневский Сергей Викторович
1. Чеболь за партой
Фантастика:
попаданцы
дорама
5.00
рейтинг книги
Надуй щеки!

Довлатов. Сонный лекарь 2

Голд Джон
2. Не вывожу
Фантастика:
альтернативная история
аниме
5.00
рейтинг книги
Довлатов. Сонный лекарь 2

Глубокий космос

Вайс Александр
9. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Глубокий космос

Отмороженный 12.0

Гарцевич Евгений Александрович
12. Отмороженный
Фантастика:
боевая фантастика
попаданцы
рпг
фантастика: прочее
5.00
рейтинг книги
Отмороженный 12.0

Последний Паладин. Том 3

Саваровский Роман
3. Путь Паладина
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 3

Старый, но крепкий 3

Крынов Макс
3. Культивация без насилия
Фантастика:
рпг
уся
фэнтези
5.00
рейтинг книги
Старый, но крепкий 3

Академия проклятий. Книги 1 - 7

Звездная Елена
Академия Проклятий
Фантастика:
фэнтези
8.98
рейтинг книги
Академия проклятий. Книги 1 - 7

Возвращение Безумного Бога 3

Тесленок Кирилл Геннадьевич
3. Возвращение Безумного Бога
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Возвращение Безумного Бога 3

Я все еще не князь. Книга XV

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

Первый среди равных. Книга III

Бор Жорж
3. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
6.00
рейтинг книги
Первый среди равных. Книга III

Сердце Дракона. Том 12

Клеванский Кирилл Сергеевич
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Сердце Дракона. Том 12

Аномальный наследник. Пенталогия

Тарс Элиан
Аномальный наследник
Фантастика:
фэнтези
6.70
рейтинг книги
Аномальный наследник. Пенталогия

Черный рынок

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