Вход/Регистрация
Программирование на 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; }

  • Читать дальше
  • 1
  • ...
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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