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

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

Жанры

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

Но вы должны сделать так, чтобы память, выделенная для предыдущего начала (origin), была освобождена до того, как будет задано новое начало. Это можно сделать в методе setOrigin:. -(void) setOrigin: (XYPoint *) pt { if (origin) [origin release]; origin = [[XYPoint alloc] init]; [origin setX: pt.x andY: pt.y]; }

Если вы синтезируете свои методы доступа, то можете сделать так, чтобы компилятор автоматически разрешил эту проблему. 8.4. Расширение через наследование: добавление новых переменных экземпляра

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

методы или переменные экземпляра. Переменные вы можете только добавлять, а методы— добавлять или замещать.

Вернемся к простым классам ClassA и ClassB и внесем некоторые изменения. Добавим в ClassB новую переменную экземпляра у. @interface ClassB: ClassA { int у; } -(void) printVar; @end

Может показаться, что ClassB будет иметь только одну переменную экземпляра (с именем у), но, исходя из предыдущего объявления, на самом деле он имеет две. Он имеет его собственную переменную экземпляра у и наследует переменную х из класса ClassA.

Примечание. Этот класс имеет также переменные экземпляра, которые наследует из класса NSObject, но мы пока будет игнорировать этот факт. Ниже приводится простой пример этой концепции (программа 8.8). // Расширение переменных экземпляра #import <Foundation/Foundation.h> // Объявление и определение ClassA @interface ClassA: NSObject { int x; } -(void) initVar; @end @implementation ClassA -(void) initVar { x = 100; } @end // Объявление и определение ClassB @interface ClassB: ClassA { int у; } -(void) initVar; -(void) printVar; @end @implementation ClassB -(void) initVar x = 200; у = 300; ) -(void) printVar { NSLog (@"x = %i", x); NSLog (@"y = %i", y); } @end int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; ClassB *b = [[ClassB alloc] init]; [b initVar]; // uses overriding method in ClassB [b printVar]; // reveal values of x and y; [b release]; [pool drain]; return 0; }

Вывод программы 8.8 x = 200 у = 300

Объект b класса ClassB инициализируется путем вызова метода initVar, определенного в классе ClassB. Этот метод замещает метод initVar из ClassA, присваивает значение 200 переменной х (унаследованное из ClassA) и значение 300 — переменной у (определенной в ClassB). Метод printVar выводит значения этих переменных экземпляра.

Есть много других тонкостей, связанных с выбором метода в ответ на сообщение, особенно в тех случаях, когда получателем является один из нескольких классов. Это динамическое связывание (dynamic binding), которое рассматривается в следующей главе. 8.5. Абстрактные классы

Мы закончим эту главу, добавив еще немного терминологии, связанной с понятием наследования.

Иногда классы создаются просто для того, чтобы упростить другим создание подкласса. Такие классы называют абстрактными (abstract) или абстрактными суперклассами. В этом классе определяются методы и переменные экземпляра, но при этом не предполагается, что кто-либо будет создавать экземпляры из этого класса. Например, р нет никакого смысла определить объект непосредственно из корневого объекта NSObject. Foundation framework (см. часть II) содержит несколько абстрактных классов. Например, класс Foundation NSNumber является абстрактным классом, который был создан для работы с числами как с объектами. Для хранения целых чисел и чисел с плавающей точкой обычно требуются разные размеры памяти. Для каждого числового типа существуют отдельные подклассы NSNumber. Поскольку эти подклассы, в отличие от их абстрактных суперклассов, реально существуют, их называют конкретными (concrete) подклассами. Каждый конкретный подкласс является дочерним классом класса NSNumber и называется кластером (cluster). Когда вы отправляете сообщение классу NSNumber для создания нового объекта типа integer, используется соответствующий подкласс, чтобы выделить память для этого объекта и задать его значение. Эти подклассы

на самом деле являются частными. Вы не можете выполнить непосредственный доступ к этим подклассам сами; доступ осуществляется косвенно через абстрактный суперкласс. Абстрактный суперкласс представляет общий интерфейс для работы со всеми типами числовых объектов и позволяет вам не знать, какой тип числа вы сохранили в вашем числовом объекте и как задавать и считывать его значение. Упражнения

Добавьте в программе 8.1 новый класс с именем ClassC, который является подклассом класса ClassB. Создайте метод initVar, который присваивает значение 300 своей переменной экземпляра х. Напишите тестовую процедуру, которая объявляет объекты классов ClassA, ClassB и ClassC и вызывает их методы initVar.

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

Внесите изменения в программу 8.1, чтобы добавить новый класс с именем ClassB2, который, как и ClassB, является подклассом класса ClassA. Что вы можете сказать о связи между ClassB и ClassB2? Укажите иерархические связи между классом NSObject, классом ClassA, ClassB и ClassB2. Что является суперклассом для ClassB? Что является суперклассом для ClassB2? Сколько подклассов может иметь класс, и сколько он может иметь суперклассов?

Напишите метод Rectangle с именем translate:, который принимает в качестве своего аргумента вектор с именем XYPoint (xv,yv). Сделайте так, чтобы он смещал начало прямоугольника (origin) на указанный вектор.

Определите новый класс с именем GraphicObject и сделайте его подклассом NSObject. Определите переменные экземпляра в этом новом классе следующим образом. int fillColor; // 32-битный цвет BOOL filled; // Заполняется ли объект? int lineColor; // 32-битный цвет линии

Напишите методы, которые задают и считывают значения определенных выше переменных.

Сделайте класс Rectangle подклассом GraphicObject. Определите новые классы Circle (Круг) и Triangle (Треугольник), которые тоже являются подклассами GraphicObject. Напишите методы, чтобы задавать и считывать параметры для этих объектов, вычислять длину окружности и площадь круга, периметр и площадь треугольника.

Напишите метод для Rectangle с именем intersect:, который принимает прямоугольник как аргумент и возвращает прямоугольник, представляющий площадь перекрытия этих прямоугольников. Например, для двух прямоугольников, показанных на рис. 8.Ю, метод должен возвращать прямоугольник, начало (origin) которого находится в точке (400, 420), ширина (width) равна 50 и высота (height) равна 60.

Рис. 8.10. Пересечение прямоугольников

Если прямоугольники не пересекаются, нужно возвратить прямоугольник с шириной и высотой 0 и началом (0,0).

Напишите метод для класса Rectangle с именем draw, который рисует прямоугольник из знаков «минус» и «вертикальная черта». Следующая последовательность кодов Rectangle *myRect = [[Rectangle alloc] init]; [myRect setWidth: 10 and Height: 3]; [myRect draw]; [myRect release]; _______ | | | | | | _______

Глава 9. Полиморфизм, динамический контроль типов и динамическое связывание

В этой главе описываются возможности языка Objective-C, которые делают его столь мощным языком программирования и отличают его от некоторых объектно-ориентированных языков, таких как C++. Это три ключевых концепции: полиморфизм, динамический контроль типов и динамическое связывание.

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

Александр Агренев. Трилогия

Кулаков Алексей Иванович
Александр Агренев
Фантастика:
альтернативная история
9.17
рейтинг книги
Александр Агренев. Трилогия

Кукловод

Злобин Михаил
2. О чем молчат могилы
Фантастика:
боевая фантастика
8.50
рейтинг книги
Кукловод

Идеальный мир для Лекаря 26

Сапфир Олег
26. Лекарь
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 26

Потомок бога

Решетов Евгений Валерьевич
1. Локки
Фантастика:
попаданцы
альтернативная история
аниме
сказочная фантастика
5.00
рейтинг книги
Потомок бога

Тринадцатый VI

NikL
6. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Тринадцатый VI

Я до сих пор царь. Книга XXXII

Дрейк Сириус
32. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я до сих пор царь. Книга XXXII

Я - истребитель

Поселягин Владимир Геннадьевич
1. Я - истребитель
Фантастика:
альтернативная история
8.19
рейтинг книги
Я - истребитель

Тихие ночи

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

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

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

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

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

Древесный маг Орловского княжества 4

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

Темный Лекарь 9

Токсик Саша
9. Темный Лекарь
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Темный Лекарь 9

Эволюционер из трущоб. Том 12

Панарин Антон
12. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Эволюционер из трущоб. Том 12

Я уже граф. Книга VII

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