Статьи

AS3 101: Ветвление — Basix

В нашей третьей части AS3 101 мы встречаем мозги операции. Все приложения должны иметь хотя бы небольшую встроенную логику, поэтому мы говорим именно о ветвлении . Мы встретимся с оператором if оператором switch и кое-чем, что называется lookup table (или хэш-картой).


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


Ветвление — это общий термин, который дается конструкциям в нашем коде, который позволяет нам делать выбор и делать то или иное, в зависимости от заданного условия. Это то, что называется «управление потоком», потому что оно может делать разные вещи в зависимости от условий. Существует множество других терминов для этого аспекта программирования, включая условия или условные операторы , логику или даже разговорный оператор if . Главное, что нужно понять, это то, что ветвление — это в основном мозг операции, логика, которая придает вашей программе некоторый интеллект. Без ветвления вы не сможете добиться многого в качестве программиста.

Думайте о ветвлении, как о старых рассказах « Выбери свое приключение» . Если вы не помните их, они были «книгами об играх», где вы начали читать на странице 1, но вскоре им был предоставлен выбор: если вы решили сделать X, перейдите на страницу 10. Если вы решили сделать Y, перейдите к стр. 15 Прочитать книгу прямо через не имеет смысла. Вы должны были сделать свой выбор и прыгать по книге, как литературный прыжок. При любом чтении книги вы читали только часть страниц. Каждый раз, когда вы достигли конца раздела, вы переходили на тот или иной путь. См . Страницу Википедии в книге « Выберите свое приключение» для получения дополнительной информации.

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

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

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

Любопытный может захотеть немного почитать о причинности в Википедии.


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

Мы собираемся написать довольно простую ветвь, которую мы можем. Мы будем использовать оператор if .

1
2
3
if (true) {
    trace(«This happened.»);
}

Давайте разберемся с этим. Во-первых, у нас есть ключевое слово if . Это зарезервированное слово в языке ActionScript, которое обозначает начало блока if . Сразу же после этого условие . Условие идет между скобками. Отсутствие скобок приведет к ошибке; Я поднимаю это, потому что я все еще иногда забываю вставить их! Мы поговорим об условиях на следующем шаге, но сейчас мы просто будем использовать true в качестве нашего условия. После условия — открывающаяся фигурная скобка. Это отмечает начало блока операторов ActionScript, которые будут выполняться, если (и только если) условие выполнено. После блока оператора (ов) идет закрывающая скобка, обозначающая конец блока.

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

Таким образом, если условие оказывается истинным, выполняется все, что находится между фигурными скобками. С другой стороны, если условие заканчивается как ложное, тогда весь блок кода между фигурными скобками пропускается. Иди вперед и запусти этот фильм. Поскольку слово true является истинным условием, вы увидите след на панели «Вывод». Закройте фильм и измените код так, чтобы он выглядел так:

1
2
3
if (false) {
    trace(«This happened.»);
}

Запустите это снова; потому что ложное не является истинным условием, вы не увидите, чтобы что-то случилось. Блок был пропущен.

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


Помните то условие, которое мы использовали в шаге 2? Это не так много условий. В сущности, вся структура if — это просто формальность, потому что мы используем логический литерал true , что означает, что блок всегда выполняется. Естественно, что первый пример — упрощенная версия. Чтобы использовать условия, нам нужно ознакомиться с логическими выражениями.

Вы, вероятно, знаете, что логический тип данных является чем-то родным для AcionScript. Переменная, которая является логическим значением, может быть истинной или ложной . Стоит отметить, что хотя мы используем слова true и false , на самом деле это ключевые слова в языке. Они не являются строками «истина» и «ложь».

Таким образом, логическое значение может иметь одно из двух значений: true или false . Иногда вы можете думать об этом как о да или нет , или 0 или 1 (что сводится ко всему бинарному аспекту этого … но это сейчас не важно). Таким образом, логическое выражение — это целое выражение, которое оценивается как одно из двух значений: истина или ложь . В Википедии есть небольшая статья на эту тему , которая может быть дополнена более глубоким обсуждением выражений в целом .

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

оператор имя Верно если пример
== равенство левая сторона равна правой стороне в значении 42 == 42

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

Например, 5 == 3 будет ложным . «Привет» == «Привет» будет правдой .

оператор имя Верно если пример
знак равно Неравенство левая сторона не равна правой стороне по значению 42! = 5

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

Например, 5! = 3 будет правдой . «Привет»! = «Привет» будет ложным .

оператор имя Верно если Примеры)
< Меньше, чем левая сторона численно меньше правой 5 <42
<= Меньше или равно левая сторона численно меньше или равна правой стороне 5 <= 42
42 <= 42
> Больше чем левая сторона численно больше, чем правая 42> 5
> = Больше или равно левая сторона численно больше или равна правой стороне 42> = 5
42> = 42

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

оператор имя Верно если пример
&& Логическое И левая сторона верна и правая сторона верна 42 == 42 && 5 == 5
|| Логическое ИЛИ По крайней мере одна сторона верна 5 == 5 || 42 == 5

Если вы когда-либо занимались булевой математикой, то, вероятно, это будет знакомо. Они оба смотрят на логические значения с обеих сторон и возвращают логическое значение в зависимости от комбинации значений.

И вернет истину, только если оба операнда верны. Если один из них ложный, тогда все выражение ложно. Это все равно, что сказать: «Если магазин мороженого открыт и у них сегодня мороженое с чизкейком, то я куплю его». Оба эти условия должны быть верными, чтобы результат был положительным. Магазин может быть открыт, но у них нет чизкейка, поэтому мы не будем его покупать. Или, может быть, у них был чизкейк на складе сегодня, но они закрылись рано, поэтому, очевидно, мы ничего не можем купить. Оба должны быть истинными, чтобы конечный результат был правдой.

ИЛИ вернет истину, если хотя бы один из операндов верен. Он вернет ложь, только если оба ложны. Мы можем представить сценарий, в котором мы могли бы сказать: «Если будет открыт либо местный пиццерий, либо корпоративная сеть пиццерий, то я получу пиццу на ужин». В этом случае мы не так разборчивы, как в случае с мороженым. Мы готовы к любой пицце, и пока одна из них открыта, мы готовы. Если оба закрыты, то нам не повезло. Конечно, оба могут быть открыты, но в этом случае мы все равно получим пиццу.

Что поднимает концепцию короткого замыкания логического выражения. Обратите внимание, что с AND и OR существует 4 возможных комбинации значений. Три из этих значений будут одинаковыми, одно будет другим значением.

И правда ложный
правда правда ложный
ложный ложный ложный
ИЛИ правда ложный
правда правда правда
ложный правда ложный

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

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

В этих случаях ActionScript оценивает «достаточно» всего выражения для определения результата. Зачем вам это знать? По причинам оптимизации. Если у вас есть выражение OR, и один из операндов представляет собой простое значение логической переменной, а другой — сложный оператор, включающий множество вычислений и вызовов функций, то вам было бы немного лучше, если бы в этом выражении сначала была указана простая переменная , Если это правда, тогда нет необходимости выполнять сложный оператор. ActionScript знает об этом и поэтому полностью пропустит выполнение этого оператора. В приложениях, критичных к производительности, такую ​​оптимизацию вы можете легко выполнить.

оператор имя Верно если пример
! Логическое НЕ меняет правую сторону ! (42 == 5)

Восклицательный знак просто переворачивает состояние логического выражения справа от него. Например:

1
2
var thisIsTrue:Boolean = true;
trace(!thisIsTrue);

Результатом будет отправка false на панель вывода.

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


Давайте изложим всю теорию, которую мы только что научились использовать. Давайте изменим это, если (true) на что-то более реалистичное:

1
2
3
4
var state:String = «foo»;
if (state == «foo») {
    trace(«The current state is ‘foo'»);
}

Итак, это не совсем реалистично, но теперь у нас есть сравнение на равенство, происходящее в условии. Запустите это, и вы должны увидеть след. Попробуйте изменить либо значение переменной состояния, либо строку, использованную при сравнении. Например:

1
2
3
4
var state:String = «bar»;
if (state == «foo») {
    trace(«The current state is ‘foo'»);
}

Итак, что происходит? Ну, почти то же самое, что и раньше, за исключением того, что у нас есть более интересные условия. Мы начнем с установки значения переменной состояния (предположительно, чтобы отслеживать текущее состояние нашего приложения). Затем мы нажимаем на блок if и вычисляем выражение в скобках. Если все выражение имеет значение true, то мы выполняем вещи между фигурными скобками. Единственная реальная разница в том, что наше выражение более сложное.

Но это не плохо; это просто оператор равенства, используемый для сравнения значения состояния с литеральной строкой «foo». В первом примере это именно то, что состояние , поэтому условие истинно, и мы видим след. Во втором примере, состояние не «foo», поэтому мы не видим след.

Давайте попробуем немного более сложный пример:

1
2
3
4
5
6
var state:String = «bar»;
var loggedIn:Boolean = true;
 
if (state == «foo» && loggedIn) {
    trace(«Welcome, logged in user! The current state is ‘foo'»);
}

Опять же, у нас есть переменная состояния . У нас также есть другая переменная loggedIn , гипотетически отслеживающая, вошли ли мы в систему или нет. Наше условие фактически проверяет две вещи: во-первых, является ли текущее состояние «foo», и также, если мы вошли в систему. Если коротко, то все это ложь (оператор AND требует, чтобы оба были истинными ), и больше ничего не происходит.

Вам может быть интересно, как мы узнали, что сначала сравнивать состояние с «foo», а не проверять, является ли «foo» И loggedIn истинным. Есть что-то, называемое приоритетом операторов, которое во многом похоже на то же самое в математике (если бы я продолжал это поднимать, вы бы подумали, что у меня есть запас математики, чтобы продать вас). Например, в математическом выражении 2 + 3 * 4 вы сначала умножаете 3 на 4, а затем добавляете 2, потому что умножение имеет приоритет (происходит первым) над сложением. Все те логические операторы, которые мы обсуждали на последнем шаге, также имеют приоритет. Я не буду вдаваться в формальное обсуждение этого вопроса, но вы можете найти информацию о приоритете оператора ActionScript здесь и здесь, а также довольно вызывающую статью о приоритете в целом в Википедии здесь .

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

1
if (state == «foo» && score > 100) {…

Будет оцениваться точно так же, как:

1
if (score > 100 && state == «foo») {…

Помимо ранее упомянутого короткого замыкания, которое может произойти, эти утверждения точно такие же.

Полезно думать о AND и OR как о разделителях для множества условий, которые все должны быть оценены. Они работают как запятые в списке для разделения элементов.


Следует еще кое-что понять, как практически любое значение, независимо от того, является ли оно логическим значением, может использоваться в тех местах, где ожидается логическое значение, например, в условии оператора if (но не назначается переменным, тип данных которых является логическим; не то, что я имею в виду). Например, рассмотрим это:

1
2
3
if (42) {
    trace(«It was true.»);
}

Запустите этот фрагмент, и вы увидите след. Но 42 не булево! Как это случилось? Что ж, когда мы добавляем числовое значение к условию, оно оценивается следующим образом: если число равно 0, то обрабатывать условие как ложное. Другой мудрый, относитесь к нему как к правде. Вы можете увидеть эффект этого, поменяв 42 с 0.

Строки следуют аналогичным правилам. Любая строка за исключением пустой строки будет истинной; пустая строка будет ложной.

1
2
3
4
5
6
7
if («a») {
    trace(«‘a’ is true»);
}
 
if («») {
    trace(«You’ll never get here.»);
}

Точно так же любой сложный объект, такой как Arrays, Sprites и MovieClips, XML и URLRequests, может принимать логическое значение. Попробуйте это:

1
2
3
4
var sprite:Sprite = new Sprite();
if (sprite) {
    trace(«We have a Sprite.»);
}

Запустите его и снова вы увидите след. Однако попробуйте следующее:

1
2
3
4
var sprite:Sprite;
if (sprite) {
    trace(«We have a Sprite.»);
}

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

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

1
2
var sprite:Sprite;
sprite.x = 100;

Принимая во внимание, что следующее обеспечивает сеть безопасности:

1
2
3
4
var sprite:Sprite;
if (sprite) {
    sprite.x = 100;
}

Еще один лакомый кусочек, тогда мы будем двигаться дальше. Как упоминалось ранее, распространенная ошибка — путать оператор присваивания (один знак равенства) с оператором равенства (два знака равенства). Наше состояние, которое выглядит так:

1
if (state == «foo») {…

Можно легко случайно написать:

1
if (state = «foo») {…

Это тонкая разница и легко сделать. Но давайте посмотрим, что происходит, когда здесь используется оператор присваивания. Это не булево выражение как таковое, но, как уже упоминалось ранее на этом шаге, когда ожидается булево значение, любое значение, переданное ему, будет преобразовано в логическое значение. Результатом операции присваивания является присваиваемое значение. То есть выражение state = «foo» в действительности оценивается как «foo» . Итак, согласно тому, что мы узнали ранее, непустая строка будет иметь значение true , поэтому в этом случае условие выполняется, и мы запускаем код. Однако мы не проверяем, является ли состояние «foo» — это может быть любое другое значение — мы всегда присваиваем его значению «foo» и всегда выполняем код. Эта ошибка на самом деле приводит к нефатальному предупреждению при компиляции: «Предупреждение: 1100: назначение в условном выражении. Вы имели в виду == вместо =?», Но SWF все равно будет работать и в нем просто будет содержаться неисправная логика. Если бы не предупреждение компилятора, вы, вероятно, потратили бы несколько минут, если не часов, пытаясь отследить ошибку.


Хорошо, давайте двигаться дальше! Там так много всего, что можно охватить. Сам по себе оператор if чрезвычайно полезен, но иногда мы хотим не только выполнить некоторый код, если что-то истинно, но и выполнить другой бит кода, если это то же самое не соответствует действительности. Например, еще на шаге 1 я использовал пример отправки формы и либо отображения ошибок, либо отправки данных, в зависимости от того, является ли условие ввода верным или нет. В этом случае мы бы хотели обратиться к оператору if / else . Это выглядит так:

1
2
3
4
5
if (state == «foo») {
    trace(«Current state: ‘foo'»);
} else {
    trace(«It is not ‘foo'»);
}

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


Иногда существует более двух возможностей. Для этого обратимся к остальному, если . Они идут после начального if , но перед закрытием else (если присутствует). Например:

1
2
3
4
5
6
7
if (state == «foo») {
 
} else if (state == «bar») {
 
} else {
 
}
01
02
03
04
05
06
07
08
09
10
11
if (state == «foo») {
 
} else if (state == «bar») {
 
} else if (state == «fud») {
 
} else if (state == «splat») {
 
} else {
 
}

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

1
2
3
4
5
if (state == «foo») {
 
} else if (state == «bar») {
 
}

Стоит отметить еще одну деталь: если бы у нас была цепочка из других if , ActionScript считает, что это хорошо выполненная работа, как только он находит первое истинное условие. Так что, если второе, если успешно, тогда не имеет значения, если четвертое, если , также будет успешным в текущих условиях; второй раз, если выполняется код блока, весь блок завершен. Например:

1
2
3
4
5
6
7
8
var state:String = «bar»;
if (state == «foo») {
    trace(«Foo state.»);
} else if (state == «bar») {
    trace(«You’ll see this one for sure.»);
} else if (state == «bar») {
    trace(«Pigs are flying.»);
}

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

1
2
3
4
5
6
7
8
if (state == «foo»)
{
    trace
}
else
{
    trace
}

Кажется, что это одобренный Adobe метод, иногда называемый стилем ANSI. Однако, если вы обнимаетесь, вам все равно может оказаться проще читать длинный переходной блок, если вы опустите слово else if или else вниз на следующей строке, например, так:

1
2
3
4
5
6
if (state == «foo») {
    trace
}
else {
    trace
}

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

1
if (state == «foo») {trace(«foo»)}else{trace(«bar»);}

или это

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
if (state == «foo»)
 
         {
 
 
    trace(«foo»)
 
 
 
}
 
 
 
 
 
else {
 
 
 
 
 
    trace(«bar»);
 
 
 
 
 
 
 
 
 
                        }

На самом деле существует довольно много вариаций стилей, и все они имеют имена и обоснования. Отправляйтесь в Википедию для подробного обсуждения.

И это обсуждение приводит к изменению без скобок, которое я защищаю в некоторых случаях.

1
if (state == «foo») trace(«You’re on foo»);

Если весь блок, который должен быть выполнен в ответ на истинное условие, представляет собой одну строку, то вы можете опустить фигурные скобки. В то время как предыдущий фрагмент имеет для меня наибольшее значение (он практически читается как английское предложение: «Если состояние равно foo, проследите, что вы находитесь на foo»), пробел снова не имеет значения. Вы иногда увидите это:

1
2
if (state == «foo»)
   trace(«You’re on foo.»);

В то время как идеально подходит и может сделать для хороших компактных веток

1
2
3
4
5
6
7
8
if (state == «foo»)
    trace(«You’re on foo.»);
else if (state == «bar»)
    trace(«You’re on bar.»);
else if (state == «fud»)
    trace(«You’re on fud.»);
else
    trace(«What are you on?»);

Проблема возникает, когда вам обязательно нужно добавить вторую строку. ActionScript не настолько умен, чтобы просто рассматривать код между if и else, если он является блоком … это либо код между фигурными скобками, либо первый оператор после if , если фигурных скобок нет. В какой-то момент после первоначального написания вышеуказанного кода вам, вероятно, придется изменить его на:

1
2
3
4
if (state == «foo») {
    trace(«You’re on foo.»);
    trace(«Which is a lovely place to be.»);
} … etc.

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

Последнее замечание по этому поводу, а затем мы продолжим: имейте в виду, что правило без скобок относится к первому утверждению после if (или else ), а не к первой строке. Если вы попытались втиснуть два оператора в одну строку, вот так:

1
if (state == «foo») trace(«You’re on foo.»);trace(«Which is a lovely place to be.»);

Вторая трассировка считается отдельным оператором и не будет учитываться как часть предложения if . Этот фрагмент сам по себе всегда будет отслеживать «Каким прекрасным местом быть», независимо от значения состояния.


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

01
02
03
04
05
06
07
08
09
10
11
12
13
switch (state) {
    case «foo»:
        trace(«You’re on foo.»);
        break;
    case «bar»:
        trace(«You’re on bar.»);
        break;
    case «fud»:
        trace(«You’re on fud.»);
        break;
    default:
        trace(«What are you on?»);
}

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

Итак, давайте разберемся с этим. Во-первых, это ключевое слово switch . Так же, как ключевое слово if (или var или function ), оно запускает все это.

Затем, также как и блок if , есть набор скобок. Однако вместо того, чтобы вычислять содержимое скобок в true или false , переключатель просто вычисляет скобки в соответствии со своим значением. В этом случае переменная состояния содержит String, поэтому коммутатор «запомнит» это значение при выполнении.

Затем несколько фигурных скобок. Пока что ничего особенного.

Тогда мы доберемся до ключевого слова case . Это особая сущность в ActionScript, которая используется только внутри блока переключателей , например, как вы можете использовать ключевое слово else, только если оно следует за блоком if . Сразу после слова case у нас есть значение (в данном случае буквенная строка), и весь регистр завершается двоеточием. Здесь происходит то, что значение регистра («foo» для первого) сравнивается со значением в переключателе (независимо от того, какое состояние в данный момент удерживается). Если есть совпадение, то выполняется код под оператором case . Если нет, то он пропускает этот код и переходит к следующему случаю.

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


Эти операторы break в блоке switch действительно важны. Без них код, выполняющийся в результате сопоставления, будет продолжать выполняться. Например, следующий код является вариантом последнего примера, за исключением случаев, когда не используются операторы break. Установка переменной состояния в «foo» даст вам неожиданные результаты:

01
02
03
04
05
06
07
08
09
10
11
var state:String = «foo»;
switch (state) {
    case «foo»:
        trace(«You’re on foo.»);
    case «bar»:
        trace(«You’re on bar.»);
    case «fud»:
        trace(«You’re on fud.»);
    default:
        trace(«What are you on?»);
}

Если вы запустите это, вы увидите, что у вас есть все четыре следа. Почему? Потому что без перерывов код начинает выполняться после первого совпадения. Неважно, что второй случай не совпадает; оператор switch в основном говорит: «Хорошо, я нашел соответствие. Я начну выполнять весь код, который не является регистром или строкой по умолчанию , пока не увижу разрыв .

Вы можете думать, что это ужасно неудобно, и на самом деле это может быть. 9 раз из 10 вы будете писать операторы switch с перерывом для каждого случая . Это соответствует серии условий if / else-if / else.

Однако такое поведение может быть весьма полезным, если вы поймете, к какой гибкости оно может привести. Представьте, что вы хотите сказать, было ли число частью последовательности Фибоначчи. Конечно, есть лучшие способы сделать это, но следующий пример иллюстрирует использование дела без перерыва:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
var value:Number = 5;
switch (value) {
    case 1:
    case 2:
    case 3:
    case 5:
    case 8:
    case 13:
    case 21:
    case 34:
        trace(«Part of the sequence.»);
        break;
    default:
        trace(«Just a regular number.»);
}

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

1
2
3
4
5
if (value == 1 || value == 2 || value == 3 || value == 5 || value == 8 || value = 13 || value == 21 || value == 34) {
    trace(«Part of the sequence.»);
} else {
    trace(«Just a regular number.»);
}

Вы можете видеть, что версию коммутатора легче читать и еще легче изменить.

1
2
3
4
5
6
7
8
switch (state) {
    case «member»:
        show
    case «logged in»:
        showLogOutButton();
    case «logged out»:
        showLogInButton();
}

Что лучше: оператор if или оператор switch? Ну, действительно, в конце концов, все сводится к тому, что вы предпочитаете. Однако иногда бывают сценарии, когда один может быть более удобным, чем другой.

Операторы switch работают, когда все, что вы делаете, проверяет текущее значение некоторой переменной, особенно если это ситуация, когда вы делаете одно для одного значения, другое для другого значения и третье для третьего значения и т. Д.

Если заявления обеспечивают большую гибкость. Вы можете проверить на значение одной переменной в первом if, затем на значение совершенно другой переменной в else if. Кроме того, проще связать воедино более сложное условие, такое как

1
if (value > 10 && value < 20)

Большинство программистов сходятся во мнении, что если оператор switch выполним, его обычно легче читать.

Однако есть один аспект, который может повлиять на ваше решение в приложениях, критичных к производительности: если операторы имеют тенденцию работать быстрее, чем эквивалентные операторы switch . Не очень много, но этого может быть достаточно, чтобы сделать цикл анимации более плавным. В моих тестах оператор switch , в зависимости от сложности и в какой момент условие выполняется, может быть на 20% (возможно, больше, в зависимости) медленнее, но имейте в виду, что одна ветвь займет всего одну тысячную часть второй (или около того). 20% тысячных долей секунды — это не много, если вы не выполняете много-много-много таких веток одновременно; возможно в игре или рендеринге 3D сцены.

В конечном счете, технически они делают одно и то же, и это действительно вопрос вкуса.


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

Таблица поиска состоит из одного из типов агрегированных данных (то есть одного из встроенных объектов, которые содержат более одного значения): массив, объект или словарь.

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

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

1
2
3
4
5
6
7
var lookup:Object = new Object();
lookup[«foo»] = «You’re on foo.»;
lookup[«bar»] = «You’re on bar.»;
lookup[«fud»] = «You’re on fud.»;
 
var state:String = «foo»;
trace(lookup[state]);

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

Далее мы строим наш стол. Мы назначаем возможные значения переменной состояния («foo», «bar» и «fud») в качестве ключей на таблице, используя квадратные скобки. Этим клавишам присваивается значение , соответствующее этому ключу. Мы делаем это для всех возможных значений, а затем наша таблица строится.

Затем мы определяем нашу переменную состояния. Достаточно просто.

Теперь в последней строке мы смотрим значение из таблицы, фактически принимая решение (хотя это своего рода предопределенность). Выражение lookup [состояние] использует значение состояния в качестве ключа для таблицы поиска и оценивает значение, связанное с этим ключом. То есть оценивается первое состояние , в данном случае «foo». Итак, у нас есть поиск [«foo»] . Затем это оценивается как «Your’e on foo», потому что это то, что мы положили в таблицу для этого ключа. Затем эта строка отправляется в функцию трассировки, и мы видим сообщение на панели «Вывод».

Думайте об этом как о таблице из двух столбцов, например:

ключ значение
«Foo» «Ты на фу».
«бар» «Ты в баре».
«Фуд» «Вы в обмане.»

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

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


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

Начните с открытия Flash и создания нового документа ActionScript 3.0 Flash.

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


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

Я нарисовал квадрат, круг и треугольник, используя стандартные инструменты рисования Flash. Я правлю Держите их примерно одинакового размера. Не стесняйтесь менять цвет.


Для каждой фигуры нажмите на нее, затем нажмите F8, чтобы открыть диалоговое окно «Преобразовать в символ». Дать каждому имя; для удобства следования вы можете сопоставить мои имена. Я использовал «Квадрат», «Круг» и «Треугольник». Я надеюсь, что вы можете определить, какое имя соответствует какому символу.

Убедитесь, что точка регистрации установлена ​​в центр

Если ваше окно выглядит так:

Нажмите кнопку «Дополнительно». Flash запомнит ваш выбор, поэтому, если вы уже нажали эту кнопку и не вернулись к «Основному», тогда ваше окно будет выглядеть так:

Теперь нажмите «Экспорт» для ActionScript и убедитесь, что там, где написано «Класс», в поле ввода текста читается «Квадрат», «Круг» или «Треугольник». Опять же, я надеюсь, что вы можете понять, какой из них должен сказать, какой

Нажмите «ОК».

Всплывающее окно предупредит вас, что «определение этого класса не может быть найдено в пути к классам, поэтому оно будет автоматически сгенерировано в SWF-файле при экспорте». Просто нажмите «ОК» здесь. Вы можете испытать желание проверить «Больше не показывать». вариант, но я предлагаю, чтобы вы позволяли Flash предупреждать вас каждый раз. Возможно, вам это сейчас не нужно, но вам это понадобится. Лучше будет вручную отклонить эти предупреждения, когда они не требуются, чем делать что-то неправильно и не получать предупреждение.

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


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

Мы уменьшим размер кнопок до 1/3 от их первоначального размера и разместим их в ряд вдоль верхней части.

Дайте каждому имя экземпляра. Опять же, чтобы упростить отслеживание, я рекомендую вам придерживаться имен, которые я использую, но имейте в виду, что имена действительно не имеют значения, только если вы используете те же имена, где это уместно. Нажмите на каждую кнопку фигуры и в инспекторе свойств введите «square_mc», «circle_mc» и «triangle_mc», что имеет смысл.


Теперь перейдем к коду. Создайте новый слой, назовите его «действия» или «код» или тому подобное, заблокируйте его и щелкните в кадре 1 этого слоя. Нажмите F9 (Windows) / Opt-F9 (Mac), чтобы открыть панель «Действия».

Добавьте следующий код:

1
2
3
4
5
6
7
square_mc.addEventListener(MouseEvent.CLICK, onToolClick);
circle_mc.addEventListener(MouseEvent.CLICK, onToolClick);
triangle_mc.addEventListener(MouseEvent.CLICK, onToolClick);
 
function onToolClick(me:MouseEvent):void {
    trace("onToolClick");
}

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

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

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

Как мы определяем, какие детали использовать? Мы используем ветвление. Та-да!


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

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

1
2
3
4
5
6
7
8
stage.addEventListener(MouseEvent.CLICK, onCanvasClick);
 
function onCanvasClick(me:MouseEvent):void {
    var shape:MovieClip = new Square();
    shape.x = me.stageX;
    shape.y = me.stageY;
    addChild(shape);
}

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

Сначала мы добавляем еще один прослушиватель событий CLICK, на этот раз для сцены, чтобы он регистрировался каждый раз, когда мы щелкаем в любом месте фильма. Эта функция создает новый экземпляр нашего квадратного символа, а затем размещает его в соответствии с расположением мыши в событии. Каждый MouseEvent несет с собой информацию о рассматриваемом событии, включая положение мыши, когда событие произошло. Чтобы убедиться, что мы помещаем наш новый квадрат в положение мыши, мы можем просто взять stageX и stageY из объекта события, переданного в функцию. Наконец, чтобы увидеть квадрат, нам нужно добавить его в список отображения.

Если вы запустите это сейчас, у вас должен быть полностью функционирующий фильм, за исключением того, что он всегда рисует квадраты. Мы исправим это дальше, но сейчас я хочу отметить, что onCanvasClick описывает наше общее поведение. Единственная деталь, которая не позволяет нам быть более гибкими, — это та часть, где написано new Square () . Нам также нужно создать новый Круг и новый Треугольник. Но все остальное — форма var, позиционирование и добавление фигуры к сцене — нужно будет делать независимо от типа фигуры.

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


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

Внутри onCanvasClick добавьте строку в самом верху функции:

1
if (me.target != stage) return;

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

Так что, если мы нажмем на что-то, кроме стадии, то мы выполним одну строку кода: мы вернемся . Это просто останавливает выполнение функции. Другими словами, если мы нажмем на что-то, кроме сцены, просто остановитесь здесь и сделайте вид, что ничего не произошло.

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


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

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

Мы можем снова использовать ветвление для обеспечения логики. Мы заменим этот оператор if с последнего шага оператором switch , который легко сделает то, что мы ищем:

1
2
3
4
5
6
switch (me.target) {
    case square_mc:
    case circle_mc:
    case triangle_mc:
        return;
}

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

Между прочим, обычно я пропустил бы последний шаг, но мне показалось, что это хороший способ добавить дополнительную практику, используя операторы if !


Это может показаться знакомым, если вы читали эту серию с самого начала; Еще в первом уроке по переменным мы разработали простое приложение для отслеживания текущей кнопки в группе кнопок. Мы возьмем ту же идею, но сделаем с ней что-то немного другое. Мы также собираемся пропустить идею отключения текущей кнопки и визуальной обработки ее; Я призываю вас разработать эту функциональность самостоятельно, в качестве упражнения, если вам это нужно. Опять же, сейчас мы фокусируемся на логике ветвления, чтобы заставить это приложение работать на довольно специфическом уровне.

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

1
var currentTool:MovieClip;

После объявления этой переменной вернитесь к функции onToolClick и замените строку трассировки:

1
currentTool = me.target as MovieClip;

Теперь всякий раз, когда мы нажимаем на кнопку инструмента, этот клип кнопки отслеживается в переменной currentTool. Поскольку эта переменная объявлена ​​вне какой-либо функции, она сохраняется. Мы будем обращаться к содержимому этой переменной из функции onCanvasClick и разместим там нашу логику ветвления.

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


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

Мы будем переделывать на CanvasClick. В этой функции убедитесь, что это выглядит так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
function onCanvasClick(me:MouseEvent):void {
    if (me.target != stage) return;
    var shape:MovieClip;
    if (currentTool == square_mc) {
        shape = new Square();
    } else if (currentTool == circle_mc) {
        shape = new Circle();
    } else if (currentTool == triangle_mc) {
        shape = new Triangle();
    } else {
        return;
    }
    shape.x = me.stageX;
    shape.y = me.stageY;
    addChild(shape);
}

Последние три строки такие же, как и раньше, но первая строка просто взорвалась. Давайте пройдемся по тому, что случилось.

Сначала мы просто объявляем переменную формы, не добавляя в нее одновременно значение. Мы сделаем это дальше.Таким образом, мы проверяем, является ли currentTool квадратичным MovieClip. Если это так, то мы создаем новый квадрат, чтобы привести его в форму. Если это не так, то мы проверяем, является ли currentTool circle_mc. Если это так, мы создаем новый круг. Но если это не квадратная и не круглая кнопка, мы проверяем, чтобы убедиться, что это кнопка треугольника, и если это так, поместим новый треугольник в переменную формы. Если по какой-то причине это не какая-либо из этих трех возможностей, мы вернемся .

Большая часть этого, вероятно, довольно легко понять, но давайте еще раз посмотрим на остальное . Что это за возврат бизнеса? Если вы помните свои функции, они потенциально могут вернуть значение. Эта функция имеет тип данных void, поэтому она не может возвращать значение. Но это может просто вернуться. Это делает функцию перестать работать, в основном. Если currentTool не является правильным значением, то мы не хотим ничего делать, поэтому мы просто выйдем из функции здесь, прежде чем что-либо еще произойдет.

Итак, почему мы просто не написали «если это квадрат, то сделайте квадрат, иначе, если это круг, то сделайте круг, а затем сделайте треугольник?» Мы могли бы иметь. Но есть две причины, почему мы этого не сделали.

Первая причина — просто охватить основы. Например, что происходит при первом запуске фильма? currentTool не имеет значения. Если бы мы начали нажимать на холст, прежде чем нажать на одну из кнопок, мы все равно получили бы Треугольник. Потому что currentTool не определен, и это не square_mc, а также не circle_mc, поэтому он подпадает под остальное . Итак, одна из причин — просто убедиться, что мы начинаем элегантно. Существуют и другие способы инициализации, например, автоматический выбор квадратной кнопки, но, как я уже сказал, покрыть основы. Поскольку приложение для рисования становится все сложнее, вы можете обнаружить, что currentTool как-то оказался с неожиданным значением из-за ошибки в программе. Лучше быть готовым к такой ситуации.

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

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


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

Снимите блок if со слова «if» до закрывающей скобки «else». Вместо него напишите эквивалентный ключ:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
function onCanvasClick(me:MouseEvent):void {
    if (me.target != stage) return;
    var shape:MovieClip;
    switch (currentTool) {
        case square_mc:
            shape = new Square();
            break;
        case circle_mc:
            shape = new Circle();
            break;
        case triangle_mc:
            shape = new Triangle();
            break;
        default:
            return;
    }
    shape.x = me.stageX;
    shape.y = me.stageY;
    addChild(shape);
}

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

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

Попробуйте это; это должно работать точно так же, как и раньше.


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

Сначала нам нужен словарь карты. Объявите его в верхней части скрипта с помощью переменной currentTool:

1
var toolMap:Dictionary = new Dictionary();

Затем нам нужно начать заполнять карту. Следующие строки должны быть:

1
2
3
toolMap[square_mc] = Square;
toolMap[circle_mc] = Circle;
toolMap[triangle_mc] = Triangle;

Мы связываем одну кнопку с соответствующим классом, который определяет символ формы. Обратите внимание, что мы не делаем toolMap [square_mc] = new Square (); вместо этого мы просто храним ссылку на сам Квадрат, а не на фактический экземпляр Квадрата. Здесь мы углубляемся в размышления, но потерпите меня.

Затем нашей функции onCanvasClick необходимо хирургически удалить блок переключателей и заменить его кодом, который будет искать наше заранее заданное значение на карте. Удалить из слова «switch» после закрывающей фигурной скобки по умолчанию. Затем измените первую строку, чтобы она выглядела так:

1
2
if (!toolMap[currentTool]) return;
var shape:MovieClip = new toolMap[currentTool]();

Вот и все!Запустить его; он должен работать точно так же, как и раньше!

Ого, что только что произошло? Это то, что вы бы назвали наукой? Или это волшебство?

Давайте оценим эти строки, как это сделал бы Flash Player, только немного медленнее. Сначала давайте посмотрим, что происходит, когда мы оцениваем toolMap [currentTool] , как часть вычисления логического выражения в условии оператора if . У нас есть переменная currentTool . Нам нужно знать, что это такое, прежде чем идти дальше. Допустим, мы нажали на кнопку с кружком, поэтому значение равно circle_mc.

Итак, теперь мы ищем toolMap [circle_mc] и ранее мы использовали имя класса круга для связывания, Circle . На данный момент мы признаем, что это ценность. Тогда применяется оператор NOT. Без оператора NOT использование Circle в качестве логического условия было бы истинным , поскольку это значение, а не NULL . Но НЕ меняет это. Таким образом, условие на самом деле ложно . Поэтому мы пропускаем оставшуюся часть строки (тело оператора if) и продолжаем.

Но если по какой-то причине мы получили недопустимое значение из таблицы поиска — например, когда мы впервые запускаем фильм, и в currentTool нет значения — это NOT null будет иметь значение true, и мы запустим строку. Это будет означать конец этой функции, поскольку мы просто возвращаемся . Опять же, мы просто покрываем основы и готовимся к исключениям из правил. Строка является эквивалентом нашего последнего else и значения по умолчанию в предыдущих итерациях . Тем не менее, это должно быть перед строкой установки переменной, потому что, если из таблицы поиска нет действительного значения, то эта строка вызовет ошибки и завершится ошибкой.

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

1
var shape:MovieClip = new Circle();

Затем мы переходим к остальной части кода, как и раньше, с переменной формы, заполненной одним из трех фрагментов MovieClips.

Сумасшедший, а? Это нормально, если это не совсем регистрируется, но я хотел показать вам, как просто принимать решения заранее и избегать больших if / elses или переключателей.

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

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


ОК, это приложение для рисования не заменит Adobe Illustrator & trade; в ближайшее время, но это дает некоторое представление о том, как приложение, основанное на инструментах или контекстах, будет использовать один из нескольких методов для изменения деталей или даже всего поведения одного и того же действия. Готовый файл Flash можно найти в загрузке этого руководства .

Логика ветвления является неотъемлемой частью всего программирования. Без возможности принимать решения ваша программа будет когда-либо делать только одно. Для того, чтобы делать умные вещи, вам нужно освоить ветви. Мы не касались тернарного оператора , также известного как выражение if , которое часто называют сокращением if / else и чрезвычайно полезно для задания переменной одного или другого значения, в зависимости от логического выражения. Если ваш мозг еще не достаточно полон, посетите Википедию для их статьи ?: (Да, это так называется). Синтаксис в основном такой же, как «Варианты Си». Или поищите в Google «сценарий действия троичного оператора»

Одна заключительная заключительная мысль; в интригующей книге Beautiful Code , опубликованной O’Reilly , доступной на Amazon , есть глава Лоры Вингред и Кристофера Зейвальда , которые рассказывают о написании программного пакета и проведении анализа, в котором сравнивается число зарегистрированных ошибок с количество раз, код получил отступ другой вкладки. Интересно, что чем больше раз программисты вложили другое, скажем, еслизаявление и впоследствии отступ в коде, тем больше было ошибок. В следующем крупном выпуске программного обеспечения программисты предприняли целенаправленные усилия, чтобы уменьшить объем сильно загруженного кода и, что удивительно, количество ошибок уменьшилось. Я предлагаю это как предостережение о переходе за борт с условиями. Хотя определенное количество логики необходимо, написание сильно вложенных ветвей часто сбивает с толку. Именно по этой причине я рекомендую использовать таблицы поиска, когда это возможно, в качестве альтернативы традиционному оператору if или switch .

Если вы сделали это далеко, поздравляю! Вы только что завершили триекта длинных рассуждений об основах программирования применительно к ActionScript 3. Следующий шаг в этой серии расскажет о массивах и циклах. После этого мы можем начать исследовать некоторые дополнительные темы, такие как объектно-ориентированное программирование и такие вещи, как список отображения и XML. Спасибо за прочтение!