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

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

Жанры

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

Директива @public делает переменные экземпляра доступными для других методов или функций с помощью оператора-указателя (->), который описывается в главе 13. Такой доступ к переменным экземпляра не допускается практикой надежного программирования, поскольку он нарушает концепцию инкапсуляции данных (то есть скрытие классом своих переменных экземпляра). Внешние переменные

Если написать int gMoveNumber = 0;

в начале программы — вне любого метода, определения класса или функции, — то ее значение можно использовать из любого места данного модуля. В этом случае gMoveNumber определяется как гло б а ль н а я переменная. Обычно принято использовать букву g как первую букву глобальной переменной, чтобы обозначить для читателя программы ее область действия.

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

Внешней (external) переменной является переменная, чье значение может изменяться другими методами или функциями. Внутри модуля, из которого требуется доступ к этой переменной, она объявляется обычным образом, перед ее объявлением ставится ключевое слово extern. Это указывает системе, что требуется доступ к глобально определенной переменной из другого файла. Ниже показан пример объявления переменной gMoveNumber как внешней переменной. extern int gMoveNumber;

Модуль, в котором появилось это объявление, может выполнять доступ к переменной gMoveNumber и изменять ее значение. Другие модули тоже могут выполнять доступ к значению gMoveNumber, используя в своем файле аналогичное объявление extern.

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

Второй способ определения внешней переменной — это объявление переменной вне любой функции с ключевым словом extern перед этим объявлением и явным присваиванием начального значения этой переменной, например, extern int gMoveNumber = 0;

Однако при таком способе компилятор предупредит вас, что вы объявили переменную как extern и одновременно присвоили ей значение. Использование слова extern делает его объявлением, а не определением для переменной, а объявление не вызывает выделения памяти для переменной — это происходит в результате определения. В приведенном примере это правило нарушается, поскольку объявление интерпретируется как определение (поскольку переменной присваивается начальное значение).

При работе с внешними переменными можно объявлять переменную как extern во многих местах, но определить ее можно только один раз. Рассмотрим программу как пример использования внешних переменных. Мы определили класс с именем Foo и ввели следующий код в файл main.m: #import "Foo.h" int gGlobalVar = 5; int main (int argc, char *argc[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Foo *myFoo = [[Foo alloc] init]; NSLog (@"%i", gGlobalVar); [myFoo setgGlobalVar: 100] NSLog (@"%i", gGlobalVar); [myFoo release]; [pool drain]; return 0; }

Определение глобальной переменной gGlobalVar в этой программе делает ее значение доступным для любого метода (или функции), где используется соответствующее объявление extern. Предположим, что используется метод класса Foo с именем setgGlobalVar:. -(void) setgGlobalVar: (int) val { extern int gGlobalVar; gGlobalVar = val; }

Программа выведет следующие результаты. 5 100

Таким образом, метод setgGlobalVar: может выполнять доступ к внешней переменной gGlobalVar и изменять ее значение.

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

Только что показанный пример нарушает принцип инкапсуляции данных и практику надежного объектно-ориентированного программирования. Но вам может потребоваться работа с переменными, значения которых должны быть доступны для вызова из различных методов. Может показаться, что нет смысла делать переменную gGlobalVar переменной экземпляра в классе Foo, надежнее «скрыть» ее в классе Foo путем ограничения доступа к ней методами-установщиками (setter) и методами-получателями (getter), определенными для этого класса.

Теперь вы знаете, что любая переменная, определенная вне метода, является не только глобальной, но и внешней переменной. Но существует много ситуаций, когда нужно определить переменную, которая является глобальной, но не является внешней. Иначе говоря, вам нужно определить глобальную переменную, которая будет локальной для определенного модуля (файла). Имеет смысл определять такую переменную, если доступ к ней требуется только тем методам, которые содержатся в конкретном определении класса. Это можно сделать, определив переменную как статическую (static) внутри файла, содержащего секцию implementation для конкретного класса.

Если следующий оператор помещен вне любого метода (или функции), то значение gGlobalVar будет доступно из любой последующей точки файла, содержащей это определение, но будет недоступно из методов или функций, содержащихся в других файлах. static int gGlobalVar = 0;

Напомним, что методы класса не имеют доступа к переменным экземпляра (подумайте, почему это относится к данному случаю). Но вам может потребоваться, чтобы какой-либо метод класса имел доступ к переменным и мог задавать их значения. В качестве простого примера можно указать метод класса, выделяющий память для объектов (alloc), который должен следить за числом объектов. Это можно сделать, создав статическую переменную внутри файла секции implementation для этого класса. Метод, выделяющий память для объектов, может выполнять непосредственный доступ к этой переменной, поскольку она не будет переменной экземпляра. Пользователям данного класса необязательно знать об этой переменной. Поскольку она определена как статическая переменная в файле секции implementation, ее область действия будет ограничена этим файлом, поэтому пользователи не будут иметь непосредственного доступа к этой переменной и концепция инкапсуляции данных не будет нарушена. Вы можете написать метод для считывания значения этой переменной, если требуется доступ извне этого класса.

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

Антимаг

Гедеон Александр и Евгения
1. Антимаг
Фантастика:
фэнтези
6.95
рейтинг книги
Антимаг

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

Сапфир Олег
7. Лекарь
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 7

Камень. Книга вторая

Минин Станислав
2. Камень
Фантастика:
фэнтези
8.52
рейтинг книги
Камень. Книга вторая

На границе империй. Том 9. Часть 3

INDIGO
16. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 3

Предопределение

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

Отморозок 2

Поповский Андрей Владимирович
2. Отморозок
Фантастика:
попаданцы
5.00
рейтинг книги
Отморозок 2

Кодекс Охотника. Книга XXII

Винокуров Юрий
22. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXII

Студиозус

Шмаков Алексей Семенович
3. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Студиозус

Законы Рода. Том 7

Мельник Андрей
7. Граф Берестьев
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Законы Рода. Том 7

Гранит науки. Том 2

Зот Бакалавр
2. Героями не становятся, ими умирают
Фантастика:
фэнтези
5.00
рейтинг книги
Гранит науки. Том 2

Паладин из прошлого тысячелетия

Еслер Андрей
1. Соприкосновение миров
Фантастика:
боевая фантастика
попаданцы
6.25
рейтинг книги
Паладин из прошлого тысячелетия

Петля, Кадетский Корпус. Книга четвертая

Алексеев Евгений Артемович
4. Петля
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Петля, Кадетский Корпус. Книга четвертая

Чехов. Книга 2

Гоблин (MeXXanik)
2. Адвокат Чехов
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Чехов. Книга 2

Газлайтер. Том 28

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