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

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

Жанры

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

Мы определили класс Square как подкласс класса Rectangle, который объявлен в заголовке файла Rectangle.h. Здесь не требуется добавлять какие-либо переменные экземпляра, но добавлены новые методы setSide: и side.

Для квадрата достаточно задать только одну сторону, которая представляется как два числа. Все это скрыто от пользователя класса Square. Пользователю не нужно думать об этих деталях, поскольку здесь действует инкапсуляция, о которой мы говорили раньше.

В методе setSide: используется метод, наследуемый из класса Rectangle, задающий ширину и высоту прямоугольника. Таким образом, setSide: вызывает метод setWidth:andHeight: из класса Rectangle, передавая параметр s как значение для ширины (width) и высоты (height).Больше ничего не требуется. Тот, кто будет работать с объектом класса Square, может задавать размеры квадрата с помощью метода setSide: и использовать методы из класса Rectangle для вычисления площади и периметра квадрата. Ниже показана тестовая программа 8.3 и ее вывод для нашего нового класса Square. #import "Square.h" #import <Foundation/Foundation.h> int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Square *mySquare = [[Square alloc] init]; [mySquare setSide: 5]; NSLog (@"Square s = %i", [mySquare side]); NSLog (@"Area = %i, Perimeter = %i", [mySquare area], [mySquare perimeter]); [mySquare release]; [pool drain]; return 0; }

Вывод программы 8.3 Square (квадрат) s = 5 Area (площадь) = 25, Perimeter (периметр) = 20

Способ, с помощью которого был определен класс Square, является базовым методом работы с классами в Objective-C: расширение того, что уже кем-то сделано, чтобы реализовать то, что вам нужно. Помимо этого, существует механизм категорий (category), который позволяет добавлять новые методы к существующему определению класса по модульному принципу, то есть без необходимости постоянно добавлять новые определения в файлы секций interface и implementation. Это особенно удобно в тех случаях, когда вы не имеете доступа к исходному коду. Описание категорий см. в главе 11. Класс для точки и выделение памяти

Класс Rectangle используется только для хранения размеров прямоугольника. В реальных графических приложениях требуется следить за всевозможной дополнительной информацией, например, цветом заполнения прямоугольника, цветом линий, точкой начала координат прямоугольника (origin) внутри окна и т.д. Для этого можно легко расширить существующий класс. Сейчас мы реализуем идею начала координат прямоугольника. Примем за начало координат декартовы координаты (х, у) левого нижнего угла прямоугольника. Если вы разрабатываете чертежное приложение, эта точка может представлять местоположение прямоугольника внутри окна (рис. 8.4).

Рис. 8.4. Прямоугольник, нарисованный в окне На рис. 8.4 точка начала координат прямоугольника представлена как (xl,y 1). Вы можете расширить класс Rectangle, чтобы сохранять координаты х,у точки начала прямоугольника в виде двух отдельных значений или определить класс с именем XYPoint (возможно, вы помните об этой задаче из упражнения 7 главы 3). #import <Foundation/Foundation.h> @interface XYPoint: NSObject { int x; int y; } @property int x, y; (void) setX: (int) xVal andY: (int) yVal; @end

Теперь вернемся к классу Rectangle. Нам нужно сохранять координаты начала прямоугольника, поэтому требуется добавить к определению этого класса еще одну переменную экземпляра с именем origin. @interface Rectangle: NSObject { int width; int height; XYPoint *origin; }

Вполне разумно добавить метод, с помощью которого задаются и считываются координаты начала прямоугольника. Мы не будем здесь синтезировать методы доступа (accessor methods) для координат начала, а напишем их сами. Директива @class

На данный момент вы можете работать с прямоугольниками (и квадратами), задавая их ширину, высоту и координаты начала. Рассмотрим в полном виде файл Rectangle.h секции interface. #import <Foundation/Foundation.h> @class XYPoint; @interface Rectangle: NSObject { int width; int height; XYPoint *origin; @property int width, height; -(XYPoint *) origin; -(void) setOrigin: (XYPoint *) pt; -(void) setWidth: (int) w andHeight: (int) h -(int) area; -(int) perimeter; @end

В файле Rectangle.h использована новая директива: @class XYPoint;

Она требуется нам, поскольку компилятору нужно знать, что представляет собой XYPoint, когда он встречается в одной из переменных экземпляра, определенных для Rectangle. Имя этого класса используется также в объявлениях типов аргумента и возвращаемого значения для наших методов setOrigin: и origin соответственно. У вас есть и другой вариант выбора — импортировать файл заголовка, например, в следующем виде: #import "XYPoint.h"

Директива @class эффективнее, поскольку компилятору не нужно обрабатывать весь файл XYPoint.h (хотя это небольшой файл); компилятору достаточно знать, что XYPoint является именем класса. Если нужна ссылка на один из методов класса XYPoint, то директива @class недостаточна, поскольку компилятору потребуется дополнительная информация: аргументы, передаваемые методу, их типы, тип возвращаемого значения метода.

Заполним формы для нового класса XYPoint и новых методов класса Rectangle, чтобы протестировать их в программе. В программе 8.4 имеется файл секции implementation для класса XYPoint.

Сначала в ней показаны новые методы для класса Rectangle. #import "XYPoint.h" -(void) setOrigin: (XYPoint *) pt { origin = pt; -(XYPoint *) origin { return origin; ) @end

Затем показаны полные определения классов XYPoint и Rectangle и тестовая программа для их проверки. #import <Foundation/Foundation.h> @interface XYPoint: NSObject { int x; int y; } @property int х, у; -(void) setX: (int) xVal andY: (int) yVal; @end #import "XYPoint.h" @implementation XYPoint @synthesize x, y; -(void) setX: (int) xVal andY: (int) yVal { x = xVal; у = yVal; } @end #import <Foundation/Foundation.h> @class XYPoint; @interface Rectangle: NSObject { int width; int height; XYPoint *origin; } @property int width, height; -(XYPoint *) origin; -(void) setOrigin: (XYPoint *) pt; -(void) setWidth: (int) w andHeight: (int) h; -(int) area; -(int) perimeter; @end #import "Rectangle.h" @implementation Rectangle @synthesize width, height; -(void) setWidth: (int) w andHeight: (int) h width = w; height = h; -(void) setOrigin: (XYPoint *) pt origin = pt; -(int) area { return width * height; } -(int) perimeter { return (width + height) * 2; } -(Point *) origin { return origin; } @end #import "Rectangle.h" #import "XYPoint.h" int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Rectangle *myRect = [[Rectangle alloc] init]; XYPoint * myPoint = [[XYPoint alloc] init]; [myPoint setX: 100 andY: 200]; [myRect setWidth: 5 andHeight: 8]; myRect.origin = myPoint; NSLog (@"Rectangle w = %i, h = %i", myRect.width, myRect.height); NSLog (@"Origin at (%i, %i)"> myRect.origin.x, myRect.origin.y); NSLog (@»Area = %i, Perimeter = %i», [myRect area], [myRect perimeter]); [myRect release]; [myPoint release]; [pool drain]; return 0; }

Вывод программы 8.4 Rectangle (Прямоугольник) w = 5, h = 8 Origin at (Координаты начала) (100, 200) Area (Площадь) = 40, Perimeter (Периметр) = 26

Внутри процедуры main выделена память и инициализирован объект класса Rectangle с именем myRect и объект класса XYPoint с именем myPoint. С помощью метода setX:andY: объекту myPoint присваивается значение (100, 200). После задания ширины и высоты этого прямоугольника (5 и 8 соответственно) вызывается метод setOrigin, чтобы задать для координат начала прямоугольника точку, указанную в myPoint. Затем с помощью трех вызовов процедуры NSLog выполняется считывание и вывод этих значений. В выражении myRect.origin.x

считывается объект класса XYPoint, возвращенный методом доступа origin, и применяется оператор «точка» для получения координаты «х» начала прямоугольника. В следующем выражении считывается координата «у» начала прямоугольника: myRect.origin.y Классы, владеющие своими объектами

Можете ли вы объяснить результаты вывода программы 8.5? #import "Rectangle.h" #import "XYPoint.h" int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Rectangle *myRect = [[Rectangle alloc] init]; XYPoint *myPoint = [[XYPoint alloc] init]; [myPoint setX: 100 andY: 200]; [myRect setWidth: 5 and Height: 8]; myRect.origin = myPoint; NSLog (@"Origin at (%i, %i)", myRect.origin.x, myRect.origin.y); [myPoint setX: 50 andY: 50]; NSLog (@"Origin at (%i, %i)", myRect.origin.x, myRect.origin.y); [myRect release]; [myPoint release]; [pool drain]; return 0; }

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

Герой

Бубела Олег Николаевич
4. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.26
рейтинг книги
Герой

Кодекс Охотника. Книга XVII

Винокуров Юрий
17. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XVII

Кай из рода красных драконов 4

Бэд Кристиан
4. Красная кость
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Кай из рода красных драконов 4

Имя нам Легион. Том 3

Дорничев Дмитрий
3. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 3

Мое ускорение

Иванов Дмитрий
5. Девяностые
Фантастика:
попаданцы
альтернативная история
6.33
рейтинг книги
Мое ускорение

Второгодка. Книга 2. Око за око

Ромов Дмитрий
2. Второгодка
Фантастика:
героическая фантастика
альтернативная история
фэнтези
5.00
рейтинг книги
Второгодка. Книга 2. Око за око

Законник Российской Империи. Том 2

Ткачев Андрей Юрьевич
2. Словом и делом
Фантастика:
городское фэнтези
альтернативная история
аниме
дорама
6.40
рейтинг книги
Законник Российской Империи. Том 2

Золотой ворон

Сакавич Нора
5. Все ради игры
Фантастика:
зарубежная фантастика
5.00
рейтинг книги
Золотой ворон

Мой муж – чудовище! Изгнанная жена дракона

Терин Рем
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Мой муж – чудовище! Изгнанная жена дракона

Второй кощей

Билик Дмитрий Александрович
8. Бедовый
Фантастика:
юмористическое фэнтези
городское фэнтези
мистика
5.00
рейтинг книги
Второй кощей

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

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

Дважды одаренный. Том VI

Тарс Элиан
6. Дважды одаренный
Фантастика:
аниме
альтернативная история
фэнтези
фантастика: прочее
5.00
рейтинг книги
Дважды одаренный. Том VI

Деревенщина в Пекине 3

Афанасьев Семен
3. Пекин
Фантастика:
попаданцы
дорама
5.00
рейтинг книги
Деревенщина в Пекине 3

Система Возвышения. (цикл 1-8) - Николай Раздоров

Раздоров Николай
Система Возвышения
Фантастика:
боевая фантастика
4.65
рейтинг книги
Система Возвышения. (цикл 1-8) - Николай Раздоров