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

Кочан Стивен

Шрифт:

Вывод программы 9.2 2/5 10 + 2.5i

Переменная dataValue объявляется как объект типа id, поэтому dataValue можно использовать для хранения в программе объекта любого типа. Отметим, что в строке объявления не используется «звездочка»: id dataValue;

Объекту f 1 типа Fraction присваивается дробь 2/5, переменной с1 типа Complex присваивается значение (10 + 2.5i). Оператор dataValue = f 1;

сохраняет f1 в dataValue. Вы можете вызвать с dataValue любой из методов, допустимых в объекте типа Fraction, хотя dataValue имеет тип id, а не Fraction. Но как система определяет, какой метод нужно вызвать, если в dataValue можно сохранять объект любого типа? Если система встречает выражение с сообщением [dataValue print];

откуда она знает, какой метод print нужно вызвать? Ведь методы print определены и в классе Fraction, и в классе Complex.

Как уже говорилось, система Objective-C всегда следит за классом, которому принадлежит объект. Это также определяется концепциями динамического контроля типов и динамического связывания: система принимает решение о классе объекта и о методе для его динамического вызова во время выполнения, а не во время компиляции.

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

Во втором случае а с1 типа Complex присваивается dataValue. Затем выполняется следующее выражение с сообщением: [dataValue print];

Поскольку теперь dataValue содержит объект, принадлежащий классу Complex, для выполнения выбирается метод print из этого класса.

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

Например, метод draw можно использовать для рисования графических объектов на экране. У вас могут быть различные методы draw, определенные для каждого из ваших графических объектов, таких как тексты, окружности, прямоугольники, окна и т.д. Если графический объект, который нужно нарисовать, сохраняется, например, в переменной типа id с именем currentObject, то его можно нарисовать на экране, просто передав ему сообщение draw: [currentObject draw];

Вы можете сначала проверить, отвечает ли на метод draw объект, хранящийся в currentObject. Ниже вы увидите, как это делать. 9.3. Проверка на этапе компиляции и проверка на этапе выполнения

Поскольку тип объекта, хранящегося в переменной id, во время компиляции может быть неизвестен, некоторые проверки откладываются до выполнения программы (runtime). Рассмотрим следующую последовательность кодов. Fraction *f1 = [[Fraction alloc] init]; [f1 setReal: 10.0 andlmaginary: 2.5];

Поскольку метод setReakandlmaginary: применяется к комплексным числам, а не к дробям, при компиляции программы, содержащей эти строки, появится предупреждающее сообщение. ргодЗ.т: In function 'main':(B функции 'main') prog3.m:13: warning: ’Fraction' does not respond to 'setReakandlmaginary:' (предупреждение: объект типа 'Fraction' не отвечает на 'setReakandlmaginary:')

Компилятору Objective-C известно, что И является объектом класса Fraction, поскольку он был объявлен именно так. При появлении выражения с сообщением [Н setReal: 10.0 andlmaginary: 2.5];

ему стало известно, что класс Fraction не содержит метода setReal:andlmaginary: (и не наследует его). Поэтому компилятор выдает предупреждающее сообщение.

Теперь рассмотрим следующую последовательность кодов. id dataValue = [[Fraction alloc] init]; [dataValue setReal: 10.0 andlmaginary: 2.5];

Компилятор не выводит предупреждающего сообщения, поскольку во время обработки исходного файла ему неизвестно, какой тип объекта сохраняется в dataValue.

Сообщение об ошибке не появится, пока вы не запустите программу, содержащую эти строки. Сообщение об ошибке может выглядеть следующим образом. objc: Fraction: does not recognize selector -setReakandlmaginary: (не распознается селектор -setReakandlmaginary) dynamic3: received signal: Abort trap (получен сигнал: аварийное прерывание) When attempting to execute the expression (При попытке выполнить выражение) [dataValue setReal: 10.0 and I maginary: 2.5];

Система runtime сначала проверяет тип объекта, хранящегося внутри dataValue. Поскольку dataValue содержит дробь (объект Fraction), система runtime проверяет, определен ли метод setReal:andlmaginary: для класса Fraction. Поскольку это не так, выдается сообщение, и выполнение программы прекращается. 9.4. Тип данных id и статический контроль типов

Если тип данных id можно использовать для хранения любого объекта, так почему бы нам не объявлять все объекты с типом id? Этого не следует делать по нескольким причинам.

  • Читать дальше
  • 1
  • ...
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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