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

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

Жанры

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

Рис. 8.2. Подклассы и суперклассы

Рис. 8.3. Наследование переменных экземпляра и методов

(Конечно, на рис. 8.3 не показаны другие методы или переменные экземпляра, наследуемые из класса NSObject.)

Теперь рассмотрим, как это все сочетается в программе. Для краткости поместим все объявления и определения в один файл. // Простой пример наследования #import <Foundation/Foundation.h> // Объявление и определение ClassA @interface ClassA: NSObject { int x; } -(void) initVar; @end @implementation ClassA -(void) initVar { x = 100; } @end // Объявление и определение ClassB @interface ClassB : ClassA -(void) printVar; @end @implementation ClassB -(void) printVar { NSLog (@"x = %i", x); } @end int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; ClassB *b = [[ClassB alloc] init]; [b initVar]; // будет использовать унаследованный метод [b printVar]; // раскрывает значение х; [b release]; [pool drain]; return 0; }

Вывод программы 8.1 х = 100

Мы начинаем с определения b как объекта класса ClassB. После выделения памяти и инициализации b следует передача сообщения для применения к b метода initVar. Н о в определении класса ClassB мы не видим, что определен какой-либо метод. Метод initVar был определен в классе ClassA, а поскольку ClassA является родительским классом для ClassB, он может использовать все методы ClassA. Метод initVar является унаследованным методом по отношению к ClassB. Примечание. Методы alloc и init, которые мы все время используем, никогда не определялись, поскольку мы применяем их как унаследованные методы.

После отправки объекту b сообщения initVar вызывается метод printVar для вывода значения переменной экземпляра х. Результат вывода х = 100 подтверждает, что printVar смог получить доступ к этой переменной экземпляра, поскольку он тоже был унаследован.

Концепция наследования действует вниз по всей цепочке. Так, если определить новый класс с именем ClassC, родительским классом для которого является ClassB: @interface ClassC: ClassB; @end

то ClassC унаследует все методы и переменные экземпляра класса ClassB, который, в свою очередь, наследует методы и переменные экземпляра класса ClassA, который, в свою очередь, наследует методы и переменные экземпляра NSObject.

Каждый экземпляр класса получает свои собственные переменные экземпляра, даже если они наследуются. Это означает, что объект класса ClassC и объект класса ClassB будут иметь свои собственные отдельные переменные экземпляра. Поиск подходящего метода

Прежде чем передавать сообщение объекту, надо выбрать подходящий метод для применения к этому объекту. Здесь действуют совершенно простые правила. Сначала нужно проверить класс, которому принадлежит данный объект. Если метод с нужным именем определен в этом классе, применяется этот метод. Если это не так, проверяется родительский класс, и если в нем определен данный метод, то применяется этот метод. В противном случае поиск продолжается.

Проверка родительских классов выполняется до тех пор, пока не найдется класс, который содержит указанный метод, или метод не будет найден даже в корневом классе. В первом случае вы можете действовать дальше; во втором случае возникает проблема и генерируется сообщение, аналогичное следующему: warning: 'ClassB' may not respond to '-inity* (предупреждение: 'ClassB', возможно, не отвечает ’-inity’)

Это означает, что вы ошибочно пытаетесь передать сообщение с именем unity переменной типа ClassB. Компилятор указывает, что переменные этого типа «не знают», как реагировать на такой метод. Это было определено после проверки методов класса ClassB и методов его родительских классов вплоть до корневого класса (которым в данном случае является NSObject).

В некоторых случаях, когда метод не найден, никакое сообщение не генерируется. Это означает, что используется пересылка (forwarding), описание которой приводится в главе 9. 8.2. Расширение посредством наследования: добавление новых методов

Наследование часто используется для расширения класса. Предположим, требуется разработать несколько классов для работы с двумерными графическими объектами, такими как прямоугольник, окружность и треугольник. В данном случае нас интересуют только прямоугольники (rectangle). Вернемся к упражнению 7 главы 4 и начнем с секции @interface. @interface Rectangle: NSObject { int width; int height; } @property int width, height; -(int) area; -(int) perimeter; @end

У вас будут синтезируемые методы для задания ширины (width, w) и высоты (height, h) прямоугольника, а также возврата этих значений, и ваши собственные методы для вычисления его площади (area) и периметра (perimeter). Добавим метод, который позволит задавать ширину и высоту прямоугольника в одном сообщении: -(void) setWidth: (int) w andHeight: (int) h;

Предположим, что это объявление нового класса введено в файл с именем Rectangle.h. Файл секции implementation с именем Rectangle.m может выглядеть следующим образом. #import "Rectangle.h" @implementation Rectangle @synthesize width, height; -(void) setWidth: (int) w andHeight: (int) h width = w; height = h; -(int) area { return width * height; -(int) perimeter { return (width + height) * 2; } @end

Каждое определение метода достаточно очевидно. В программе 8.2 показана процедура main для тестирования. #import "Rectangle.h" #import <stdio.h> int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Rectangle *myRect = [[Rectangle alloc] init]; [myRect setWidth: 5 andHeight: 8]; NSLog (@"Rectangle: w = %i, h = %i", myRect.width, myRect.height); NSLog (@"Area = %i, Perimeter = %i", [myRect area], [myRect perimeter]); [myRect release]; [pool drain]; return 0; }

Вывод программы 8.2 Rectangle (прямоугольник): w = 5, h = 8 Area (площадь) = 40, Perimeter (периметр) = 26

Сначала выполняются выделение памяти и инициализация объекта myRect; затем задается его ширина (5) и высота (8). Это проверяется в первой строке вывода. Затем вычисляются площадь и периметр прямоугольника путем вызова с помощью сообщения, и возвращаемые значения передаются для вывода процедуре NSLog.

Для работы с квадратами (square) можно было бы определить новый класс с именем Square и определить в нем методы, аналогичные методам класса Rectangle. Можно также учесть, что квадрат является частным случаем прямоугольника, у которого равны ширина и высота.

Поэтому проще создать новый класс с именем Square и сделать его подклассом класса Rectangle. Это позволит использовать все методы и переменные класса Rectangle помимо ваших собственных. После этого достаточно добавить только методы задания определенного значения для стороны квадрата и считывания этого значения. В программе 8.3 показаны файлы секций interface и implementation для нового класса Square. #import "Rectangle.h" @interface Square: Rectangle -(void) setSide: (int) s; -(int) side; @end #import "Square.h" @implementation Square: Rectangle -(void) setSide: (int) s { [self setWidth: s andHeight: s]; } (int) side { return width; } @end

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

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

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

Легат

Прокофьев Роман Юрьевич
6. Стеллар
Фантастика:
боевая фантастика
рпг
6.73
рейтинг книги
Легат

Легионы во Тьме 2

Владимиров Денис
10. Глэрд
Фантастика:
боевая фантастика
фэнтези
попаданцы
5.00
рейтинг книги
Легионы во Тьме 2

Страж Кодекса

Романов Илья Николаевич
1. КО: Страж Кодекса
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Страж Кодекса

Адепт. Том 1. Обучение

Бубела Олег Николаевич
6. Совсем не герой
Фантастика:
фэнтези
9.27
рейтинг книги
Адепт. Том 1. Обучение

Телохранитель Генсека. Том 4

Алмазный Петр
4. Медведев
Фантастика:
попаданцы
альтернативная история
6.00
рейтинг книги
Телохранитель Генсека. Том 4

Зеркало силы

Кас Маркус
3. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Зеркало силы

Я уже барон

Дрейк Сириус
2. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я уже барон

Буря империи

Сай Ярослав
6. Медорфенов
Фантастика:
аниме
фэнтези
фантастика: прочее
эпическая фантастика
5.00
рейтинг книги
Буря империи

Последний Паладин. Том 8

Саваровский Роман
8. Путь Паладина
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Последний Паладин. Том 8

Камень. Книга шестая

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

Мы друг друга не выбирали

Кистяева Марина
1. Мы выбираем...
Любовные романы:
остросюжетные любовные романы
прочие любовные романы
современные любовные романы
5.00
рейтинг книги
Мы друг друга не выбирали

Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Клеванский Кирилл Сергеевич
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.51
рейтинг книги
Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Рубежник

Билик Дмитрий Александрович
1. Бедовый
Фантастика:
юмористическая фантастика
городское фэнтези
мистика
5.00
рейтинг книги
Рубежник