В следующей строке объявляется метод, который возвращает значение с двойной точностью. (Подробнее об этом типе данных см. в главе 4.) -(double) retrieveDoubleValue;
Значение возвращается из метода с помощью оператора Objective-C return аналогично значению, возвращаемому из main в примерах предыдущей програм-мы. Если метод не возвращает никакого значения, нужно указать это с помощью типа void, как в следующем примере: -(void) print;
Это объявление метода экземпляра print, этот метод не возвращает никакого значения. В подобных случаях вам не нужно выполнять оператор return в конце метода. Можно выполнить return без указания какого-либо значения: return;
Указывать тип возвращаемого значения для методов необязательно, хотя практика программирования рекомендует это делать. Если тип не указан, то по умолчанию используется тип id. Подробнее о типе данных id см. в главе 9. По сути, тип id можно использовать для ссылки на любой тип объекта. Аргументы для метода
В секции @interface программы 3.2 объявляется еще два метода. -(void) setNumerator: (int) n; -(void) setDenominator: (int) d;
Оба метода экземпляра не возвращают никакого значения. Каждому методу передается целый аргумент (параметр), который указывается типом (int) перед именем аргумента. В случае setNumerator имя аргумента п. Это имя выбирается произвольно и используется методом для ссылки на аргумент. В объявлении setNumerator устанавливается,
может замедлить ее выполнение. Поэтому возьмите за правило освобождать память, как только это можно сделать.
В системе выполнения программ (runtime) Apple обеспечивается механизм очистки памяти, который называется сборкой мусора (garbage collection), но луч-ше самому управлять использованием памяти, а не полагаться на этот автома-тизированный механизм.
Вы не можете полагаться на сборку мусора для тех платформ, где она не поддерживается, например, iPhone. У вас может создаться впечатление, что вам пришлось написать намного больше кода, чтобы сделать в программе 3.2 то же самое, что и в программе 3.1. Для данного простого примера это верно, но такой способ делает упрощает написание, поддержку и расширение больших и сложных программ. Вы поймете это позже.
В последнем примере этой главы показано, как работать с несколькими дро-бями. В программе 3.3 одной дроби присваивается значение 2/3, второй дроби 3/7, и затем выполняется вывод обеих дробей. // Program to work with fractions contd (Программа для работы с дробями продолжение) #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). Это позволяет расширять и изменять определения класса, не заботясь о том, что пользователи данного класса будут работать с внутренними деталями класса. Инкапсуляция данных обеспечивает необходимый уровень изоляции между программистом и разработчиком класса.