Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Префиксы имен




Затенение

 

Переменные разных модулей или разных процедур вполне могут иметь одинаковые имена. Спрашивается, как Visual Basic определяет, какая из видимых одноименных переменных имеется в виду в каждом конкретном случае? Здесь вступает в действие эффект затенения: из нескольких одноименных переменных всегда имеется в виду более локальная переменная, то есть та, чья зона видимости меньше. То есть переменные, локальные в процедуре, имеют предпочтение перед переменными, локальными в модуле, а те - перед глобальными переменными. В этом есть глубокий смысл. Программист, объявляющий переменные в своей процедуре, может не заботиться о том, что где-то в модуле есть переменные с тем же именем. А программист, объявляющий переменные в своем модуле, может не заботиться о том, что переменные с тем же именем есть где-то в проекте.

Пример: Имеется проект из двух форм. Окно кода формы 1:

Public a As Integer

Private Sub Command1_Click()

Form2.Show

a = 1

End Sub

Окно кода формы 2:

Public a As Integer

Private b As Integer

 

Private Sub Command1_Click()

a = 2

Debug.Print Form1.a 'Печатается 1

Debug.Print a 'Печатается 2

b = 3

Debug.Print b 'Печатается 3

End Sub

 

Private Sub Command2_Click()

Dim a As Integer

Dim b As Integer

a = 4

Debug.Print a 'Печатается 4

b = 5

Debug.Print b 'Печатается 5

End Sub

 

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

Теперь несколько слов о пользе модуля кода. Удобство его в том, что он не является "хозяином". Глобальные переменные, константы, типы, процедуры, определенные в нем, являются всеобщим достоянием и могут употребляться в любых других модулях, не требуя указания "хозяина". Модуль кода и используется как вместилище таких глобальных элементов, нужных в других модулях.

 

Пусть в вашем проекте вы придумали кнопке имя Сумма, текстовому полю имя Сумма и переменной тоже имя Сумма. Так делать, конечно, нельзя: все имена перепутаются. Но и отказываться от одинаковых имен тоже никак не хочется, потому что они на ваш взгляд наиболее удачно передают смысл своих обладателей. Для того, чтобы не оказаться в такой ситуации, профессиональные программисты используют префиксы - приставки к именам. У всех элементов одной природы префикс одинаков, у элементов разной природы он разный. В нашем случае кнопка будет иметь имя cmdСумма, текстовое поле - txtСумма, переменная типа Double - dblСумма.

 

Вот какие префиксы рекомендует Microsoft для элементов управления:

 


Check box chk
Combo box, drop-down list box cbo
Command button cmd
Common dialog dlg
Directory list box dir
Drive list box drv
File list box fil
Form frm
Frame fra
Horizontal scroll bar hsb
Image img
ImageList ils
Label lbl
Line lin
List box lst
Menu mnu
Picture box pic
ProgressBar prg
RichTextBox rtf
Shape shp
Slider sld
Text box txt
Timer tmr
Toolbar tlb
TreeView tre
UpDown upd
Vertical scroll bar vsb

 

А такие - для переменных:

 


Boolean bln
Byte byt
Collection object col
Currency cur
Date (Time) dtm
Double dbl
Error err
Integer int
Long lng
Object obj
Single sng
String str
User-defined type udt
Variant vnt

 

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

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

intПеременная_цикла = intПеременная_цикла + 1

y(intПеременная_цикла) = 2 * a(intПеременная_цикла)

напишете просто

i = i + 1

y(i) = 2 * a(i)

 

19.7. К чему все эти сложности?

Давайте еще раз зададимся вопросом: зачем было выдумывать все эти глобальные и локальные переменные, зоны видимости, эффект затенения и прочее? Не проще ли было все переменные и другие элементы сделать равноправными, тогда, глядишь, и никаких зон, эффектов и прочих сложностей не понадобилось бы? Давайте попробуем так и сделать. Для простоты будем рассуждать только о переменных.

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

Итак, сделать все переменные глобальными нельзя. Тогда, может быть, сделать их всех локальными? Тоже не получится, так как это крайне затруднит обмен информацией между процедурами и модулями. А без этого обмена проект рассыпется на отдельные процедуры, как карточный домик. Вот и получается, что переменные нужны разные - и глобальные и локальные, и никуда от этого не денешься. Надо разрешать и одноименные переменные. А раз так, то нужны и зоны видимости и эффект затенения.

Встает вопрос: какую зону видимости нам выбрать для каждой конкретной переменной? Объявлять ли ее глобальной, локальной в модуле или локальной в процедуре? Здесь совет один - любую переменную делайте как можно более локальной, пусть ее зона видимости будет как можно меньше. Если ее значение нужно только в одной процедуре и больше нигде, делайте ее локальной в этой процедуре. Если ее значение нужно в нескольких процедурах одного модуля, а в других модулях нет, то делайте ее локальной в этом модуле. И только если значение переменной нужно в нескольких модулях, делайте ее глобальной. Такой подход обеспечит вашему проекту максимальную надежность и удобство в отладке.

 

Второй совет - вместо процедур без параметров используйте процедуры с параметрами. Покажу на простом примере, что я имею в виду.

Задача: Переменная равна 3. Нужно увеличить ее на 2 и результат напечатать.

Дадим переменной имя intA. Вот простейшая программа для решения задачи:

Private intA As Integer

Private Sub Command1_Click()

intA = 3

intA = intA + 2

Debug.Print intA

End Sub

Однако простейшая программа нас не устраивает. Нам нужно показать всю прелесть параметров. Для этого мы будем действовать так же, как действовал Том Сойер в книге "Приключения Гекльберри Финна", когда ему нужно было освободить негра Джима из ветхого сарайчика, где того держали взаперти. Вместо того, чтобы просто отпереть дверь имевшимся у него ключом, Том придумал массу ненужных вещей вроде веревочной лестницы, отпиленной ножки кровати и т.п. И все для того, чтобы побег из заточения был обставлен "как положено".

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

Private intA As Integer

 

Private Sub Command1_Click()

intA = 3

П1

П2

End Sub

 

Private Sub П1()

intA = intA + 2

End Sub

 

Private Sub П2()

Debug.Print intA

End Sub

Программа работает. Но этого мало. Будем усложнять дальше. Добавим к нашим процедурам параметры:

Private intA As Integer

 

Private Sub Command1_Click()

intA = 3

П1 intA

П2 intA

End Sub

 

Private Sub П1(intAA As Integer)

intAA = intAA + 2

End Sub

 

Private Sub П2(intAAA As Integer)

Debug.Print intAAA

End Sub

В чем смысл этого ужасного усложнения, этого превращения мухи в слона? Конечно, для нашего простейшего примера нет никакого смысла усложнять программу. Но когда дело дойдет до сложных проектов и процедур, здесь смысл прямой.

Зачем делить проект на процедуры, я уже рассказывал. А вот зачем понадобились параметры.

Если ваша процедура сложная и делает что-нибудь полезное, то вы вполне можете захотеть использовать ее и в других проектах. Но в другом проекте переменные скорее всего имеют другие имена, например, вместо intA там используется intB. В этом случае вам придется переписывать текст процедуры (в нашем конкретном случае везде заменить intA на intB). А переписывать не хочется. В общем, процедура теряет свою универсальность. Чтобы и переписывать не надо было и универсальность не потерять, применяются параметры. Обратите внимание, что нашим процедурам с параметрами абсолютно все равно, что переменная имеет имя intA. Нигде внутри процедуры оно не встречается, поэтому процедура уверенно делает свое дело, каково бы имя ни было. Да и программисту как-то понятней, чем занимается процедура, если он видит в ее заголовке список параметров, да еще и с подробными комментариями. Это лучше, чем глядеть в тексте процедуры на переменную intA и вспоминать, что это, черт возьми, за переменная и в чем ее смысл. В общем, совет такой - с глобальными переменными и локальными переменными модуля работайте по возможности через параметры. Что значит "по возможности"? А то, что некоторые такие переменные буквально пронизывают все процедуры проекта и организовывать для них в каждой процедуре параметры - та овчинка, которая не стоит выделки. Обычно таких переменных бывает немного и их легко просто запомнить.

 

Глава 20. Объекты пользователя

Ну вот и пришло время создания своих собственных объектов. Поговорим о них.

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

Объекты в программировании напоминают объекты реального мира. Например, чтобы описать стенные часы, мы должны описать как совокупность их составных частей (радиусы шестеренок, длину маятника и прочее – в общем, «данные») так и совокупность процессов взаимодействия этих частей (как качается маятник, как шестеренка цепляет шестеренку и так далее – в общем «процедуры и функции»).

Любой элемент управления Visual Basic - объект. Свойства элемента управления - это данные, методы - процедуры.

Почти все приложения Windows и сама операционная система Windows запрограммированы на основе объектного подхода. Типичный пример объекта в Windows – окно. Чтобы заставить окно на экране вести себя, как положено, программисту нужно описать его размер, цвет, толщину рамки и прочее (данные) плюс процессы перетаскивания его по экрану, изменения размера и прочее (процедуры и функции).

20.1. Инкапсуляция- "Объект в футляре"

Нам будет легче проникнуть в суть объектов в программировании, если мы предварительно поговорим об объектах реального мира, так как объекты в программировании очень их напоминают. Возьмем, например, игрушечный автомобиль, управляемый на расстоянии с пульта. Чтобы в нем разобраться, достаточно знать две вещи:

· Как он устроен (назовем это данные). Если объект - животное, то этим занимается анатомия.

· Как он работает (назовем это действия). Если объект - животное, то этим занимается физиология.

 

У игрушечного автомобиля данных множество. Например:

· Номер автомобиля

· Громкость звукового сигнала

· Цвет кузова

· Скорость движения в данный момент

· Высота кресел

· Величина электрического тока в двигателе в данный момент

· Толщина гайки в таком-то месте корпуса

И так далее и тому подобное.

 

Действий тоже достаточно. Например:

· Поворот по команде с пульта управления

· Торможение по команде с пульта управления

· Подпрыгивание автомобиля на маленьком камушке

· Изменение скорости вращения оси двигателя при изменении в нем электрического тока

· Изменение света фар при изменении в них электрического тока

· Возникновение жужжания двигателя при трении шестеренок друг об друга

И так далее и тому подобное.

 

Как видите, данные и действия бывают крупные и мелкие, важные и менее важные. Но нас интересует другое подразделение, а именно:

· на те данные и действия, что видны снаружи автомобиля или доступны для изменения и управления со стороны внешних объектов, например, прохожих или мальчика, держащего в руках пульт управления (такие данные и действия близки понятию глобальных переменных и процедур)

· и на те данные и действия, что не видны или не доступны (а эти близки понятию локальных)

Проведем подразделение построже и поподробнее. Данные будем делить на те, что видны снаружи (это первые 4), и те, что не видны (последние 3). Данные, видимые снаружи, назовем свойствами объекта.

Действия будем делить на те, которыми можно управлять снаружи (первые 2 действия), и те, что вызываются внутренней механикой автомобиля (остальные). Действия, вызываемые снаружи, назовем методами объекта.

 

Теперь будем подразделять свойства. Мы их разделим на две категории:

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

· Те, что снаружи менять нельзя (например, громкость звукового сигнала). Назовем их свойствами только для чтения.

 

Конструктор нашего игрушечного автомобиля при его создании стремится к тому, чтобы автомобиль был надежен, защищен и просто управлялся. Для этого он должен придерживаться двух принципов:

· Количество методов должно быть минимально необходимым. Старт, торможение, поворот налево и направо. Этого достаточно. Если разрешить управлять с пульта жужжанием двигателя и тонким процессом изменения скорости вращения колес при изменении тока в двигателе, то недолго и сжечь двигатель, нажав на пульте не ту комбинацию кнопок.

· Количество свойств для чтения-записи должно быть минимальным. Действительно, вообразим крайний случай: все данные мы сделали свойствами, да еще и для чтения-записи. Тогда любой, кому не лень, сможет в любой момент менять, например, величину тока в двигателе, что немедленно приведет к катастрофе. Или, например, вообразите, что вы едете в автомобиле, а любой прохожий может протянуть руку и покрутить баранку вашего автомобиля.

 

А теперь о том, нужно ли все данные делать свойствами, то есть делать их видимыми отовсюду. Дело вкуса. Покуда вы не делаете их свойствами для чтения-записи, это не влияет на надежность объекта. Сами решайте, нужно ли всем желающим видеть высоту сидений и величину тока. Конечно, когда речь идет о реальном игрушечном автомобиле, все получается как-то само собой: что снаружи - видно, что изнутри - не видно и ничего тут не поделаешь. Но у программиста полная свобода любое данное сделать или не сделать свойством, в том числе и для чтения-записи, и любое действие сделать или не сделать методом.

При создании объектов программисты стараются придерживаться принципа инкапсуляции, который заключается в следующем:

Данные и действия объекта представляют собой единое целое, образующее всю механику объекта, и хранятся они в одной "упаковке". Чуть позже вы увидите, что эта упаковка - отдельный модуль. Они должны быть как можно меньше видимы снаружи. Хорошо инкапсулированный объект представляет собой некий "черный ящик", эдакого "человека в футляре". Вся работа идет внутри. Внутренние данные меняются при помощи внутренних действий. Никто снаружи не может вмешаться в эту внутреннюю работу. Наружу показывается лишь тот минимум (интерфейс), который необходим для связи с окружающим миром.

Влиять на работу объекта можно только тремя способами:

· Методами

· Изменяя значения свойств для чтения-записи

· Изменяя свойства окружающего мира, например, положив на пути автомобиля камешек.

 

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

 

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

20.2. Игра "Сачок". Постановка задачи

Давайте создадим такую игру:

Как только проект запущен, из места старта на столе разлетаются во все стороны со случайными скоростями и в случайных направлениях 10 шариков. Они ведут себя как биллиардные шары на столе. Ударившись о бортик, любой шарик отскакивает по закону отражения. Примечание: Для удобства программирования я назвал по-разному 4 бортика: пол, потолок, стены. Трения нет - и шарики могут бесконечно кататься по столу. Для простоты я не стал программировать соударение шариков между собой, хотя это вполне можно было сделать. Поэтому шарики при столкновении просто пролетают друг сквозь друга. На поле присутствует Ловец (которого раньше я хотел назвать "Сачок", причем в обоих смыслах). Ловцом управляет с клавиатуры игрок. Ловец может двигаться с постоянной скоростью в 4 направлениях: вверх, вниз, влево, вправо, подчиняясь соответствующим клавишам клавиатуры, а также стоять (клавиша Ctrl). Каждый раз, когда ловец соприкасается с шариком, шарик исчезает (он пойман). Задача игрока - побыстрее поймать все 10 шариков. Счетчик времени (импульсов таймера) замирает в момент поимки последнего шарика, чтобы вы могли запомнить результат. При нажатии на кнопку "Начинай сначала" игра начинается сначала. Вот и все.

 

Что здесь будет объектом? Несмотря на то, что у нас нет опыта, интуиция подскажет нам. Конечно же, шары и ловец.




Поделиться с друзьями:


Дата добавления: 2014-12-23; Просмотров: 550; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.064 сек.