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

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

Жанры

Программирование на 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; }

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

На границе империй. Том 9. Часть 4

INDIGO
17. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 4

Мастер 11

Чащин Валерий
11. Мастер
Фантастика:
боевая фантастика
попаданцы
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Мастер 11

Камень. Книга 4

Минин Станислав
4. Камень
Фантастика:
боевая фантастика
7.77
рейтинг книги
Камень. Книга 4

Неучтенный элемент. Том 8

NikL
8. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 8

Камень. Книга 3

Минин Станислав
3. Камень
Фантастика:
фэнтези
боевая фантастика
8.58
рейтинг книги
Камень. Книга 3

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

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

На границе империй. Том 10. Часть 3

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 3

Три `Д` для миллиардера. Свадебный салон

Тоцка Тала
Любовные романы:
современные любовные романы
короткие любовные романы
7.14
рейтинг книги
Три `Д` для миллиардера. Свадебный салон

Эйзенштейн

Шкловский Виктор Борисович
Жизнь в искусстве
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Эйзенштейн

Ученик. Книга третья

Первухин Андрей Евгеньевич
3. Ученик
Фантастика:
фэнтези
7.64
рейтинг книги
Ученик. Книга третья

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

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

Эпоха Опустошителя. Том VII

Павлов Вел
7. Вечное Ристалище
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Эпоха Опустошителя. Том VII

Наследие Маозари 9

Панежин Евгений
9. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
сказочная фантастика
6.25
рейтинг книги
Наследие Маозари 9

Инженер Петра Великого 2

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