Вход/Регистрация
Программирование на Objective-C 2.0
вернуться

Кочан Стивен

Шрифт:

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

Вернемся к примеру и добавим метод printVar в класс ClassA, чтобы вывести значение его переменных экземпляра. // Объявление и определение класса ClassA @interface ClassA: NSObject { int x; -(void) initVar; -(void) printVar; @end @implementation ClassA -(void) initVar { x = 100; } -(void) printVar { NSLog (@"x = %i", x); } @end

Объявление и определение класса ClassB остается без изменений. Запустим компиляцию и выполнение программы.

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

а и b определены как объекты классов ClassA и ClassB соответственно. После выделения памяти и инициализации передается сообщение для объекта а, у которого запрашивается применение метода initVar. Этот метод определен в определении класса ClassA, поэтому выбирается именно он. Он присваивает значение 100 переменной экземпляра х и выполняет возврат. Затем вызывается метод printVar, только что добавленный в класс ClassA, чтобы вывести значение х. Выделение памяти и инициализация для объекта b класса ClassB выполняется так же как и для объекта класса ClassA, его переменной экземпляра присваивается значение 200 и выводится ее значение.

Постарайтесь разобраться, как для переменных а и b происходит выбор метода, исходя из класса, которому они принадлежат. Это одна из базовых концепций объектно-ориентированного программирования в Objective-C.

В качестве упражнения попробуйте удалить метод printVar из класса ClassB. Получится ли это? Почему? Замещение метода dealloc и ключевое слово super

Теперь, когда вы знаете, как замещать методы, вернемся к программе 8.5В, чтобы изучить более подходящий способ освобождения памяти, выделенной для origin. Метод setOrigin: выделяет память для своего собственного объекта origin класса XYPoint, и вы обязаны освободить эту память. В программе 8.6 освобождение памяти выполнял оператор: [[myRect origin] release];

Вам не нужно заботиться об освобождении всех отдельных членов класса; вы можете заместить метод dealloc (наследуемый из NSObject) и освободить там память origin.

Примечание. Мы будем замещать метод dealloc, а не метод release. Метод release иногда освобождает память, используемую объектом, а иногда нет. Он освобождает память, используемую объектом, только если никто другой не обращается к этому объекту, и делает это, вызывая метод объекта dealloc, который фактически освобождает память.

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

Для этого существует специальное ключевое слово super, которое обозначает родительский класс получателя сообщения. Для выполнения замещаемого метода нужно передать super сообщение. Выражение с сообщением [super release];

при использовании внутри метода вызывает метод release, который определен (или унаследован) в родительском классе. Этот метод вызывается в получателе сообщения, то есть в себе самом (self).

Таким образом, замещение метода dealloc для класса Rectangle выполняется следующим образом. Сначала освобождается память, занятая origin, а затем вызывается метод dealloc из родительского класса. Тем самым освобождается память, занятая самим объектом Rectangle. Ниже приводится этот метод. -(void) dealloc { if (origin) [origin release]; [super dealloc]; }

Определенный здесь метод dealloc не возвращает никакого значения. Внутри метода сначала dealloc выполняется проверка, что origin имеет ненулевое значение. Начало прямоугольника (origin), возможно, не было задано. В этом случае он имеет по умолчанию нулевое значение. Затем вызывается метод dealloc из родительского класса, который был бы унаследован классом Rectangle, если бы не был замещен.

Метод dealloc можно написать проще: -(void) dealloc { [origin release]; [super dealloc]; }

поскольку вы можете без проблем передать сообщение nil-объекту. Кроме того, к origin применяется release, а не dealloc. В любом случае, если никто другой не использует origin, release вызовет метод dealloc для origin, чтобы освободить его пространство. Используя этот метод, вы должны освобождать только те объекты-прямоугольники, для которых выделили память, не заботясь об объектах XYPoint, которые они содержат. Двух сообщений, показанных в программе 8.5, теперь достаточно, чтобы освободить память для всех объектов, в том числе объекта XYPoint, создаваемого с помощью setOrigin:. [myRect release]; [myPoint release];

Правда, остается одна проблема. Если задать для начала прямоугольника (origin) одного объекта Rectangle другие значения во время выполнения программы, то вы должны освободить память, занятую прежним началом прямоугольника, прежде чем выделить и назначить новую. Рассмотрим следующую последовательность строк: myRect.origin = startPoint; myRect.origin = endPoint; [startPoint release]; [endPoint release]; [myRect release];

Копия объекта startPoint класса XYPoint, сохраненная в элементе origin myRect, не будет освобождена, поскольку она перезаписывается вторым значением для origin (endPoint). Эта копия origin будет освобождена правильно, когда будет освобождаться сам объект прямоугольника, если применяется новый метод освобождения памяти.

  • Читать дальше
  • 1
  • ...
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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