Программирование на Objective-C 2.0
Шрифт:
Я считаю, что оно читается лучше, но окончательный выбор за вами. Выбор имен методов важен для удобочитаемости программы.
А теперь опробуем работу с новым методом. Сначала добавим объявление setTo:over: в файл секции interface, см. программу 7.2. #import <Foundation/Foundation.h> // Определение класса Fraction @interface Fraction : NSObject { int numerator; int denominator; } @property int numerator, denominator; -(void) print; -(void) setTo: (int) n over: (int) d; -(double) convertToNum; @end
Теперь добавим определение этого метода в файл implementation. #import «Fraction.h» @implementation Fraction @synthesize numerator, denominator; -(void) print { NSLog (@"%i/%i", numerator, denominator); -(double) convertToNum { if (denominator != 0) return (double) numerator / denominator; else return 1.0; -(void) setTo: (int) n over: (int) d f numerator = n; denominator = d; } @end
Новый
Вывод программы 7.2 100/200 1/3 Методы без имен аргументов
При создании имени метода имена аргументов не являются обязательными.
Метод можно объявить следующим образом. -(int) set: (int) n: (int) d;
В отличие от предыдущих примеров, для второго аргумента не задано никакого имени. Этот метод имеет имя set::, и два двоеточия означают, что методу передаются два аргумента, хотя имя одного из них не задано.
При работе с методом set:: в качестве разделителей используется двоеточие: [aFraction set: 1:3];
Практика надежного программирования рекомендует указывать имена всех аргументов при написании новых методов, так как их отсутствие затрудняет слежение за ходом программы и делает присваивания фактических параметров менее интуитивным. Операции над дробями
Продолжим работу с классом Fraction. Сначала напишем метод с именем add:, который позволит складывать одну дробь с другой. Ему будет передаваться дробь как аргумент. Ниже приводится объявление этого метода. -(void) add: (Fraction *) f;
Объявление аргумента f: (Fraction *) f
Аргумент для метода add: имеет тип класса Fraction. Звездочка обязательна. Следующее объявление является неверным: (Fraction) f
В качестве аргумента методу add: будет передаваться одна дробь, и метод будет выполнять сложение этой дроби с получателем сообщения; в следующем выражении для дроби bFraction типа Fraction будет выполнено сложение с дробью aFraction типа Fraction. [aFraction add: bFraction];
Напомним, что для сложения дробей а/b и c/d нужно выполнить следующие вычисления. а_ с_= ad + be b d bd
Поместим код для этого метода в секцию @implementation. // сложение дроби (Fraction) с дробью-получателем -(void) add: (Fraction *) f { // Для сложения двух дробей: // a/b + c/d = ((a*d) + (b*c)) / (b * d) numerator = numerator * f.denominator + denominator * f.numerator; denominator = denominator * f.denominator; }
Вы можете ссылаться
Предположим, что вы добавили эти объявления и определения для нового метода add: в файлы секций interface и implementation. Ниже приводится пример тестовой программы 7.3 и ее вывода. #import «Fraction.h» int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Fraction *aFraction = [[Fraction alloc] init]; Fraction *bFraction = [[Fraction alloc] init]; // Задание дробей 1/4 и ? и их сложение [aFraction setTo: 1 over: 4]; [bFraction setTo: 1 over: 2]; // Вывод результатов [aFraction print]; NSLog (@"+"); [bFraction print]; NSLog (@"=n); [aFraction add: bFraction]; [aFraction print]; [aFraction release]; [bFraction release]; [pool drain]; return 0; }
Вывод программы 7.3 1/4 + 1/2 = 6/8
Тестовая программа выглядит достаточно просто. Выделяется память и инициализируются два объекта класса Fraction: aFraction и bFraction. Им присваиваются значения 1/4 и 1/2 соответственно, затем дробь bFraction прибавляется к дроби aFraction и результата сложения выводится. Метод add: прибавляет аргумент к объекту сообщения, изменяя этот объект. Это проверяется, когда происходит вывод значения aFraction в конце процедуры main. Можно было бы вывести значение aFraction до вызова метода add:, чтобы увидеть значение до того, как оно было изменено с помощью метода. Ниже в этой главе мы переопределим метод add:, чтобы он не влиял на значение своего аргумента. 7.5. Локальные переменные
Вы, вероятно, заметили, что результат сложения 1/4 и 1/2 выведен как 6/8, а не 3/4. Наша процедура сложения выполняет только заданные действия, в ней не предусмотрено сокращение дроби. Добавим новый метод, с помощью которого выполняется сокращение дробей.
Сокращение дроби означает, что нужно найти наибольшее число, на которое делятся без остатка числитель и знаменатель этой дроби, и выполнить деление на это число. Это действие называется поиском наибольшего общего делителя (greatest common divisor, gcd) числителя и знаменателя. Вы уже знаете, как это делать, из программы 5.7. Используя этот алгоритм, напишем метод сокращения дроби (reduce). -(void) reduce { int u = numerator; int v = denominator; int temp; while (v != 0) { temp = u % v; u = v; v = temp; } numerator /= u; denominator /= u; }
В этом методе объявляются три целые переменные u, v и temp, которые являются локальными. Это означает, что они существуют только во время выполнения метода reduce и доступ к ним может выполняться только внутри метода, в котором они определены. В этом смысле они аналогичны переменным, объявленным в процедуре main; эти переменные тоже были локальными по отношению к main, и доступ к ним мог выполняться только внутри процедуры main. Ни один из написанных вами методов не мог иметь непосредственного доступа к этим переменным, определенным в main.