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

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

Жанры

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

Эта секция interface указы вает компилятору, что мы добавляем в класс Fraction расширение под категорией с именем MathOps. Категория MathOps содержит четыре метода экземпляра: add:, mul:, sub: и div:. Каждый метод получает в качестве аргумента дробь (fraction) и возвращает тоже дробь.

Определения всех этих четырех методов можно поместить в одну секцию implementation.Мы можем определить в одной секции implementation все методы из секции interface файла Fraction.h плюс методы из категории MathOps. Мы также можем определить методы из этой категории в отдельной секции implementation. Тогда в секции implementation для этих методов следует также идентифицировать категорию, к которой принадлежат эти методы. Как и в секции interface, имя категории после имени класса нужно заключить: в круглые скобки @implementation Fraction (MathOps) //

код для методов этой категории ... @end

В программе 11.1 для новой категории MathOps секции interface и implementation объединены в одном файле вместе с тестовой процедурой. #import "Fraction.h" @interface Fraction (MathOps) -(Fraction *) add: (Fraction *) f; -(Fraction *) mul: (Fraction *) f; -(Fraction *) sub: (Fraction *) f; -(Fraction *) div: (Fraction *) f; @end @implementation Fraction (MathOps) -(Fraction *) add: (Fraction *) f { // Для сложения двух дробей: // a/b + c/d = ((a*d) + (b*c)) / (b * d) Fraction *result = [[Fraction alloc] init]; int resultNum, resultDenom; resultNum = (numerator * f.denominator) + (denominator * f.numerator); resultDenom = denominator * f.denominator; [result setTo: resultNum over: resultDenom]; [result reduce]; return result; } -(Fraction *) sub: (Fraction *) f // Для вычитания двух дробей: // a/b - c/d = ((a*d) - (b*c)) / (b * d) Fraction *result = [[Fraction alloc] init]; int resultNum, resultDenom; resuUNum = (numerator * f.denominator) - (denominator * {.numerator); resultDenom = denominator * f.denominator; [result setTo: resultNum over: resultDenom]; [result reduce]; return result; } -(Fraction *) mul: (Fraction *) f { Fraction *result = [[Fraction alloc] init]; [result setTo: numerator * f.numerator over: denominator * f.denominator]; [result reduce]; return result; } -(Fraction *) div: (Fraction *) f { Fraction *result = [[Fraction alloc] init]; [result setTo: numerator * f.denominator over: denominator * {.numerator]; [result reduce]; return result; } @end int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Fraction *a = [[Fraction alloc] init]; Fraction *b = [[Fraction alloc] init]; Fraction *result; [a setTo: 1 over: 3]; [b setTo: 2 over: 5]; [a print]; NSLog (@" +"); [b print]; NSLog (@"----"); result = [a add: b]; [result print]; NSLog (@ "\n"); [result release]; [а print]; NSLog (@" -"); [b print]; NSLog (@"----"); result = [a sub: b]; [result print]; NSLog (@"\n"); [result release]; [a print]; NSLog (@" *"); [b print]; NSLog (@"----"); result = [a mul: b]; [result print]; NSLog (@"\n"); [result release]; [a print]; NSLog (@" /"); [b print]; NSLog (@"----"); result = [a div: b]; [result print]; NSLog (@"\n"); [result release]; [a release]; [b release]; [pool drain]; return 0; }

Вывод программы 11.1 1/3 + 2/5 ---- 11/15 1/3 - 2/5 ---- -1/15 1/3 * 2/5 ---- 2/15 1/3 / 2/5 ---- 5/6

И снова напомним, что в Objective-C вполне допустимы такие операторы, как [[a div: b] print];

В этой строке выполняется непосредственный вывод результата деления а на Ь, что позволяет избежать промежуточного присваивания результата какой- либо переменной, как в программе 11.1.Нам нужно это промежуточное присваивание, чтобы получить результирующую дробь (Fraction) и освободить память, которую она занимает. В противном случае при каждом выполнении арифметической операции над дробью будет происходить утечка памяти.

В программе 11.1 секции interface и implementation для новой категории помещены в один файл вместе с тестовой программой. Как уже говорилось выше, секция interface для категории может быть включена в исходный header-файл Fraction.h (чтобы все методы были объявлены в одном месте), или в свой соб-ственный header-файл.

Если поместить категорию в мастер-файл определения класса, все пользователи этого класса будут иметь доступ к методам данной категории. Если у вас пет возможности непосредственного внесения изменений в исходный header- файл (см. добавление категории в существующий класс из библиотеки в части II, «Foundation Framework»), то вы вынуждены хранить категорию в отдельном файле. Некоторые замечания по категориям

Отметим несколько особенностей категорий. Во-первых, хотя категория имеет доступ к переменным экземпляра исходного класса, в ней

нельзя добавить ее собственные переменные экземпляра. При необходимости нужно использовать подклассы.

Кроме того, ка тегория может замещать другой метод своего класса. Обычно это считается недопустимым в практике надежного программирования. После замещения метода вы уже нс имеете доступа к исходному методу, поэтому при замене вы должны аккуратно дублировать все функциональные возможности замещаемого метода. Если вам действительно требуется замещение какого-либо метода, используйте подклассы. При замещении метода в подклассе вы можете по-прежнему обращаться к родительскому методу, передавая сообщение super. В этом случае вам не нужно знать все особенности метода, который вы замешаете; можно просто вызвать родительский метод и добавить ваши функциональ-ные возможности в метод подкласса.

Соблюдая изложенные здесь правила, можно иметь сколько угодно категорий. Если метод определен более чем в одной категории, язык не указывает, какая из них будет использоваться.

В отличие от обычной секции interface, вам не нужно реализовать все методы, указанные в категории. Это полезно для пошаговой разработки программ, поскольку вы можете объявить все методы в категории и постепенно их реализовывать.

Расширение класса путем добавления новых методов с помощью категории влияет не только на этот класс, по и на все его подклассы. Это может быть потенциально опасным. Например, если вы добавляете новые методы в корневой объект NSObject, каждый пользователь будет наследовать эти методы. Новые методы, которые вы добавляете к существующему классу с помощью категории, возможно, будут отвечать вашим намерениям, но могут оказаться несогласованными с исходной организацией или целями класса. Например, превращение квадрата (Square) в окружность (Circle) путем добавления новой категории и некоторых методов искажает определение класса и не согласуется с практикой надежного программирования.

Кроме того, пары объект/категория должны быть уникальными. Только одна категория NSString (Private) может существовать в заданном пространстве имен Objective-C. Это может вызывать затруднения, поскольку пространство имен Objective-C совместно используется кодом программы и всеми библиотеками, структурами framework (фреймворками) и дополнительными программными модулями (plug-in). Это особенно важно для программистов Objective-C, которые пишут коды экранных заставок (screensaver), панелей предпочтений и других дополнительных модулей, поскольку их код будет вставляться в код приложения или фреймворк, которыми они не могут управлять. 11.2. Протоколы

Протокол (protocol) — это список методов, которые совместно используются классами. Методы, включенные в протокол, не имеют соответствующих реализаций (implementation): предполагается, что они будут реализованы кем-то другим. Протокол — это способ определения набора методов, которые каким-либо образом связаны с указанным именем. Эти методы обычно документируются, что позволяет вам реализовать их в ваших определениях классов.

Если вы реализуете все необходимые методы для определенного протокола, вы подчиняетесь (conform) этому протоколу или принимаете (adopt) его.

Протокол определяется просто: укажите имя протокола после директивы @protocol. После этого нужно объявить методы так же, как в секции interface. Все объявления методов вплоть до директивы @end становятся частью данного протокола.

При работе с Foundation framework вы увидите, что несколько протоколов уже определены. Один из них, NSCopying, объявляет метод, который вам потребуется реализовать, если ваш класс должен поддерживать копирование объектов с помощью метода сору (или copyWrthZone:). (Подробно тема копирования объектов рассматривается в главе 18.)

Ниже показано, как определяется протокол NSCopying в стандартном файле Foundation NSObject.h. @protocol NSCopying - (id)copyWithZone: (NSZone *}zone; @end

Если вы приняли протокол NSCopying в своем классе, то должны реализовать метод copyWithZone:. Вы сообщаете компилятору, что принимаете протокол, заключая имя этого протокола в угловые скобки (<...>) в строке @interface. Имя про школа указывается после имени класса и его родительского класса, как в следующей строке: @interlace AddressBook: NSObject <NSCopying>

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

Вечный. Книга VII

Рокотов Алексей
7. Вечный
Фантастика:
боевая фантастика
рпг
попаданцы
5.00
рейтинг книги
Вечный. Книга VII

Найденыш

Шмаков Алексей Семенович
2. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Найденыш

Санек 2

Седой Василий
2. Санек
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Санек 2

Апокриф

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

Меченный смертью. Том 2

Юрич Валерий
2. Меченный смертью
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Меченный смертью. Том 2

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

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

Император Пограничья 7

Астахов Евгений Евгеньевич
7. Император Пограничья
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Император Пограничья 7

Первый среди равных

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

Мачеха Золушки - попаданка

Максонова Мария
Фантастика:
попаданцы
сказочная фантастика
фэнтези
5.00
рейтинг книги
Мачеха Золушки - попаданка

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

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

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

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

Воронцов. Перезагрузка. Книга 2

Тарасов Ник
2. Воронцов. Перезагрузка
Фантастика:
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Воронцов. Перезагрузка. Книга 2

Черный Маг Императора 6

Герда Александр
6. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
7.00
рейтинг книги
Черный Маг Императора 6

Тайны затерянных звезд. Том 1

Лекс Эл
1. Тайны затерянных звезд
Фантастика:
боевая фантастика
космическая фантастика
фэнтези
5.00
рейтинг книги
Тайны затерянных звезд. Том 1