Январь 2011

Руководство по actionscript. часть 1, стр. 050

Использование модификаторов управления доступом при описании методов класса позволяет реализовать на практике принцип «черного ящика». В объектно-ориентированном программировании каждый объект рассматривается как черный ящик, управляемый с помощью набора внешних смоделированных кнопок. Человек, использующий эти кнопки, ничего не знает (и, впрочем, для него это неважно) о действиях, происходящих внутри объекта, — его интересует только то, чтобы объект выполнил желаемое действие. Открытые методы экземпляра класса являются теми самыми кнопками, с помощью которых программист может заставить объект выполнить определенную операцию. Закрытые методы экземпляра класса используются для выполнения других внутренних операций. Таким образом, чтобы заставить экземпляры данного класса выполнять определенные действия, в описании класса должны быть открыты только те методы, которые требуются внешнему коду. Методы, предназначенные для выполнения внутренних операций, должны быть описаны с использованием модификаторов private, protected или internal.

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

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

Руководство по actionscript. часть 1, стр. 051

,_Л_

В терминах объектно-ориентированного программирования открытые методы с открытыми переменными экземпляра класса иногда называются внешним интерфейсом класса, или API класса (Application Programming Interface — программный интерфейс приложения). Термин API также используется для обозначения общих функций, предоставляемых целой группой классов. Например, предопределенные классы среды выполнения Flash, отвечающие за отображение содержимого на экране, называются экранным API. Подобным образом набор пользовательских классов, используемых для визуализации трехмерных объектов, может называться 3D API. Помимо классов в состав программных интерфейсов могут входить и другие программные описания (например, переменные и функции). В языке ActionScript термин «интерфейс» имеет дополнительное техническое значение, которое мы рассмотрим в гл. 9. Во избежание путаницы для описания открытых методов и переменных экземпляра класса термин «интерфейс» в этой книге не применяется.

Теперь, возвращаясь к программе по созданию виртуального зоопарка, добавим модификатор управления доступом в описание метода eat ( ) класса VirtualPet. Поскольку метод еа t ( ) является одним из служебных средств, с помощью которых внешний код может управлять объектами VirtualPet, он будет реализован как открытый. Привожу измененный код:

package zoo { internal class VirtualPet { internal var petName; private var currentCalories = 1000;

public function VirtualPet (name) { this. petName = name;

}

public this

function eat ( ) { currentCalories += 100;

В таком виде метод eat ( ) класса VirtualPet является жестким, поскольку всякий раз при вызове этого метода к значению переменной currentCalories прибавляется одно и то же количество калорий. В конечном счете необходимо добиться, чтобы количество добавляемых калорий изменялось динамически в зависимости от типа пищи, которую предлагает пользователь. Чтобы предоставить внешнему коду возможность указывать количество добавляемых в процессе кормления калорий при вызове метода еat ( ), придется воспользоваться параметрами метода.

Руководство по actionscript. часть 1, стр. 052

Параметры и аргументы метода

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

Для описания параметра метода применяется следующий обобщенный код (обратите внимание, что описание параметров метода имеет такую же структуру, как и при описании параметров конструктора):

function имяМетода (идентификатор! = значение!.

идентификатор2 = значение2,

идентификаторп = значениеп) {

. }

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

имяМетода(значение1, значение2… значениеп)

В данном коде имяМетода — это имя вызываемого метода, а значение!, значение2. . . valuen — это список значений, которые по порядку присваиваются параметрам метода имяМетода. Значение параметра метода, указанное через выражение вызова (как показано в предыдущем коде), называется аргументом метода. Использование аргумента метода для задания значения параметра метода называется передачей этого значения в метод.

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

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

function имяМетода (обязательныйПараметр) { }

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

имяМетода(значение)

Отсутствие аргумента метода для обязательного параметра неизбежно приведет к ошибке либо на этапе компиляции программы (если для компиляции программы выбран строгий режим), либо на этапе ее выполнения (если программа была откомпилирована в стандартном режиме).

Теперь обновим описание метода eat ( ) класса У1Лиа1Ре^включивобязательный параметр numbe rOfCalories. Вызов метода е a t ( ) всякий раз будет обеспечивать увеличение значения переменной currentCalories текущего объекта назначение параметра numberOf Calories. Привожу обновленный код метода eat ( ):

package zoo { internal class VirtualPet { internal var petName: private var currentCalories = 1000:

public function VirtualPet (name) { this. petName = name:

}

public function eat (numberOfCalories) { this. currentCalories += numberOfCalories:

•}

}

}

Поскольку параметр numberOfCalories является обязательным, его исходное значение должно указываться во внешнем коде при вызове метода eat ( ). Попробуем реализовать это требование для объекта VirtualPet, создаваемого в конструкторе VirtualZoo. До этого момента код конструктора VirtualZoo выглядел следующим образом:

Руководство по actionscript. часть 1, стр. 053

Package zoo { public class VirtualZoo { private var pet:

public function VirtualZoo ( ) { this. pet = new VirtualPet(«Stan»); this. pet. eat( );

}

}

}

Обновленная версия кода, где в метод eat ( ) передается значение 50, будет выглядеть так:

package zoo { public class VirtualZoo { private var pet;

public function VirtualZoo ( ) { this. pet = new VirtualPet(«Stan»); this. pet. eat(50):

}

}

}

Поскольку выражение вызова из данного кода присваивает значение 5 0 параметру numberOfCalories метода eat ( ), его выполнение увеличивает значение переменной currentCalories экземпляра VirtualPet, на который ссылается переменная реt, на 5 0. Это значит, что после выполнения кода конструктора значение переменной currentCalories экземпляра, на который ссылается переменная pet, будет равно 1050.

Возвращаемые значения метода

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

function имяМетода ( ) { return значение:

}

Значение, возвращаемое методом, называется возвращаемым значением, или результатом, метода.

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

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

new Date( )

Для внутреннего представления времени в экземплярах класса Date используется «количество миллисекунд до или после полуночи 1 января 1970 года». Например, время «одна секунда после полуночи 1 января 1970 года» выражается числом 1000. Подобным образом, время «полночь 2 января 1970 года» выражается числом 86 400 000 (один день — это 1000 мс х 60 с х 60 мин х 24 ч). По умолчанию новый объект Date представляет текущее время на локальной системе.

Руководство по actionscript. часть 1, стр. 054

Для обращения к числовому значению «миллисекунд с 1970 года» определенного объекта Date используется переменная экземпляра time. Например, в следующем коде создается новый экземпляр класса Date и затем возвращается значение его переменной time:

new Date( ).time;

В результате выполнения этого кода 24 января 2007 года в 17:20 было получено значение 1 169 677 183 875, представляющее точное количество миллисекунд между полночью 1 января 1970 года и временем выполнения кода (то есть 17:20 24 января 2007 года).

Теперь вернемся к классу Virtual Pet. Чтобы иметь возможность определять возраст объектов VirtualPet, необходимо сохранить точное время создания каждого такого объекта. Для сохранения времени создания каждого объекта создадим экземпляр предопределенного класса Date в конструкторе класса VirtualPet и присвоим этот экземпляр переменной creationTime экземпляра класса VirtualPet. Привожу этот код:

package zoo { internal class VirtualPet { internal var petName: private var currentCalories = 1000: private var creationTime:

public function VirtualPet (name) { this. creationTime = new Date( ); this. petName = name:

}

public function eat (numberOfCalories) { this. currentCalories += numberOfCalories;

}

}

}

Использование переменной creationTime позволяет определить возраст любого объекта VirtualPet путем вычитания времени создания объекта из текущего времени. Это вычисление производится с помощью нового метода get Age ( ):

public function getAge ( ) { var currentTime = new Date( ); var age = currentTime. time — this. creationTime. time:

}

Чтобы возвратить вычисленный возраст объекта, воспользуемся оператором возврата:

public function getAge ( ) { var currentTime = new Date( ); var age = currentTime. time — this. creationTime. time:

return age;

}

Следующий код демонстрирует описание метода ge t Age ( ) в контексте описания класса VirtualPet:

package zoo { internal class VirtualPet { internal var petName:

private var currentCalories = 1000; private var creationTime;

public function VirtualPet (name) { this. creationTime = new Date( ); this. petName = name;

}

public function eat (numberOfCalories) { this. currentCalories += numberOfCalories;

}

public function getAge ( ) { var currentTime = new Date( ); var age = currentTime. time — this. creationTime. time; return age;

>

}

}

Теперь воспользуемся возвращенным значением метода getAge ( ) в конструкторе класса VirtualZoo. Выражение вызова метода getAge ( ) рассмотрим в следующей обновленной версии конструктора VirtualZoo:

package zoo { public class VirtualZoo { private var pet;

public function VirtualZoo ( ) { this. pet = new VirtualPet(«Stan»); this. pet. getAge( );

}

}

}

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

package zoo { public class VirtualZoo { private var pet;

public function VirtualZoo ( ) { this. pet = new VirtualPet(«Stan»); var age = this. pet. getAge( );

}

}

}

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

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

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

pet. getAge( ) / 2

Подобным же образом в следующем коде создаются два объекта класса Vi rtual Ре t, выполняется сложение возрастов созданных объектов, и затем полученная сумма присваивается локальной переменной totalAge.

package zoo { public class VirtualZoo { private var petl: private var pet2:

public function VirtualZoo ( ) { this. petl = new VirtualPet(«Sarah»); this. pet2 = new VirtualPetCLois»); var totalAge = this. petl. getAge( ) + this. pet2.getAge( );

}

}

}

Обратите внимание, что, когда оператор возврата не возвращает никакого значения, он просто завершает выполнение текущего метода. Например:

public function некийМетод ( ) { // Код. размещенный здесь (перед оператором возврата), будет выполнен

return:

// Код. размещенный здесь (после оператора возврата), выполнен не будет

}

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

Руководство по actionscript. часть 1, стр. 055

Подписи методов

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

Например, подписью для метода eat ( ) является:

eat(numberOfCalories)

А подпись метода getAge ( ) представляет собой просто:

getAge( )

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

Члены и свойства

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

В некоторых справочниках по языку ActionScript (в основном это касается справочников от корпорации Adobe) понятие «свойство» также используется для обозначения переменной экземпляра. Для того чтобы избежать путаницы, вызванной данным противоречием, в настоящей книге понятие «свойство» употребляться не будет.

В случае необходимости будет использоваться традиционное понятие объектно-ориентированного программирования — члены экземпляра (или просто члены), — обозначающее совокупность методов и переменных экземпляра. К примеру, можно сказать, что «radius не является членом класса В ох», подразумевая, что в классе Box не описаны методы или переменные с именем radius.

Руководство по actionscript. часть 1, стр. 056

Обзор программы по созданию виртуального зоопарка

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

Приложение, имитирующее зоопарк, состоит из двух классов: VirtualZoo (основной класс) и VirtualPet (класс, представляющий животных в зоопарке).

Сразу же после запуска нашего приложения экземпляр класса VirtualZoo автоматически создается средой выполнения Flash (поскольку класс VirtualZoo является основным классом приложения). В результате создания экземпляра класса VirtualZoo выполняется метод-конструктор VirtualZoo. Метод-конструктор VirtualZoo создает экземпляр класса VirtualPet, передавая в качестве единственного аргумента конструктора значение Stan.

В рассматриваемом классе VirtualPet описаны три переменных экземпляра: petName, currentCalories и creationTime. Эти переменные экземпляра

определяют кличку, количество пищи в желудке и дату рождения каждого животного.

С помощью константного выражения каждому новому объекту VirtualPet в качестве исходного значения переменной currentCalories присваивается 1000. Исходным значением переменной creationTime является объект класса Date, указывающий время создания объекта VirtualPet. При создании объекта VirtualPet переменной petName присваивается значение обязательного параметра конструктора name. Параметр конструктора name получает свое значение через аргумент конструктора, который указывается в выражении new, используемом для создания объекта VirtualPet.

В классе VirtualPet описаны два метода экземпляра: eat ( ) и getAge ( ). Метод eat ( ) увеличивает значение переменной currentCalories на указанную величину. Метод getAge ( ) вычисляет и возвращает возраст животного в миллисекундах.

Текущая версия программы по созданию виртуального зоопарка представлена в листинге 1.2.

Листинг 1.2. Программа «Зоопарк»

// Класс VirtualPet package zoo { internal class VirtualPet {

internal var petName:

private var currentCalories = 1000:

private var creationTime:

public function VirtualPet (name) { this. creationTime = new Date( ); this. petName = name:

}

public function eat (numberOfCalories) { this. currentCalories += numberOfCalories;

}

public function getAge ( ) { var currentTime = new Date( ): var age = currentTime. time — this. creationTime. time: return age;

}

}

}

// Класс VirtualZoo package zoo { public class VirtualZoo { private var pet:

public function VirtualZoo ( ) { this. pet = new Virtual Pet(«Stan»);

}

}

}

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

ГЛАВА 2

Условные операторы и циклы

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

Руководство по actionscript. часть 1, стр. 057

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

Условные операторы

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

В языке ActionScript существует два различных условных оператора: оператор if и оператор switch. Кроме того, в языке ActionScript есть и простой условный оператор? :, который кратко рассматривается в гл. 10. Подробную информацию об операторе? : можно найти в справочнике по языку ActionScript корпорации Adobe.

Оператор if

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

if (условноеВыражение) {

блокКода1 } else {

блокКода2

Когда при выполнении программы на языке ActionScript встречается оператор i f, среда выполнения Flash выполняет либо инструкции блокКода1, либо инструкции блокКода2 в зависимости от значения выражения условноеВыражение. Если результатом выражения условноеВыражение является значение true типа Boolean, то выполняется первый блок кода. Если результатом выражения условноеВыражение является значение false типа Boolean, то — второй блок кода. Если результатом выражения условноеВыражение является значение другого типа, отличного от Boolean, то среда выполнения Flash автоматически преобразует результат выражения услов — ноеВыражение в объект типа Boolean и использует результат преобразования при выборе блока кода для исполнения.

Руководство по actionscript. часть 1, стр. 058

Шу_ Правила преобразования значений различных типов в объект типа Boolean описаны в табл. 8.5.

Например, в следующем операторе i f результатом указанного условного выражения является значение true типа Boolean, поэтому переменной greeting присваивается значение Hello, а не Bon j our.

var greeting;

// Результатом условного выражения является значение true, поэтому… if (true) {

// …выполняется этот код

greeting = «Hello»; } else {

// Этот код не выполняется

greeting = «Bonjour»;

}

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

Например, предположим, что мы создаем общедоступный сайт, один из разделов которого посвящен азартным играм. Играть в них могут пользователи, возраст которых не менее 18 лет. Во время регистрации на сайте статус каждого пользователя загружается из базы данных. Загруженный статус присваивается переменной gamblingAuthorized. Если значением этой переменной является true, то возраст пользователя составляет 18 лет или более; значение false означает, что пользователю менее 18 лет.

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

if (gamblingAuthorized) {

// Расположенный здесь код отображает интерфейс раздела с азартными играми } else {

// Представленный здесь код отображает сообщение // «Доступ запрещен»

}

Зачастую условным выражением оператора if является либо выражение равенства, либо выражение отношения. Для сравнения двух значений и представления результата этого сравнения в виде значения типа Boolean (то есть либо true, либо false) в выражениях равенства и выражениях отношения используются операторы равенства и операторы отношения. Например, в следующем выражении равенства используется оператор равенства (==) для сравнения выражения Mike с выражением Margaret:

Руководство по actionscript. часть 1, стр. 059

«Mike» == «Margaret»

Результатом предыдущего выражения является значение false типа Boolean, поскольку выражение Mike не равно выражению Margaret.

Подобным образом для сравнения значения б со значением 7 в следующем выражении отношения применяется оператор «меньше чем» (<):

6 < 7

Результатом этого выражения является значение true типа Boolean, поскольку 6 меньше 7.

Как видно из предыдущих примеров, экземпляры класса String сравниваются по отдельным символам, а при сравнении экземпляров классов Number, int и uint сравниваются математические величины, хранящиеся в этих экземплярах. Обратите внимание, что при сравнении строк учитывается регистр, например выражение а не равно выражению А. Правила, используемые при сравнении значений (в каких случаях два значения равны между собой или одно значение больше или меньше другого), можно найти в описании операторов ==, ===, < и > в справочнике по языку ActionScript корпорации Adobe.

Теперь рассмотрим пример оператора if, в качестве условного выражения которого используется знак равенства. Предположим, что мы создаем программу для интернет-магазина с виртуальной корзиной для покупок. В программе создана переменная экземпляра numlterns, отражающая текущее количество товаров в корзине пользователя. Если корзина пуста, то программа выдает сообщение Ваша корзина пуста. В ином случае программа выдает сообщение Количество товаров в вашей корзине: п (где п обозначает количество товаров в корзине).

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

var basketStatus;

if (numlterns == 0) {

basketStatus = «Ваша корзина пуста»; } else {

basketStatus = «Количество товаров в вашей корзине: » + numltems;

Если значение переменной numl terns в предыдущем примере кода равно нулю, то программа присваивает переменной basketStatus следующее выражение:

«Ваша корзина пуста»

В противном случае программа присваивает переменной basketStatus следующее выражение:

«Количество товаров в вашей корзине: » + numltems

Обратите внимание на использование оператора конкатенации (+) в предыдущем выражении. Он преобразует числовое значение, хранящееся в переменной numltems, в строку и объединяет ее со строкой «Количество товаров в вашей корзине: «. Результирующим значением станет объединение двух выражений. Например, если значение переменной numl terns равно 2, то результатом операции конкатенации будет следующая строка:



Полезные ссылки
Случайные записи
  • 12.03.2011">Руководство по actionscript. часть 3, стр. 118
  • 16.03.2011">Руководство по actionscript. часть 3, стр. 030
  • 22.01.2011">Руководство по actionscript. часть 1, стр. 107
  • 01.11.2011">Первые нейросинаптические процессоры
  • 08.03.2011">Руководство по actionscript. часть 4, стр. 073
  • 17.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.122
  • 09.03.2010">Бесплатная векторная графика
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 003
  • 15.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.54
  • 20.05.2012">Владельцы iPhone5.com отказались от доменного имени из-за жалобы Apple
  • 29.02.2012">На сервисе микроблогов Futubra появился поиск
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 040
  • 19.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.27
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 051
  • 17.03.2011">Руководство по actionscript. часть 2, стр. 152
Опрос

Какие цвета вы предпочитаете?

View Results

Loading ... Loading ...