Основы ООП для ActionScript 3.0 (продолжение)

Продолжение статьи «Основы ООП для ActionScript 3.0».

Таким образом, мы переопределили (переписали) в классе MatchBox, унаследованные от базового класса Box, методы Open() и Close(). Но данные изменения относятся только к классу MatchBox, и никаких изменений в классах Box и ShoesBox не вызывают.

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

Пример:
public final function Rotate():void
{
}

Данный метод нельзя переопределить в классе потомке, так как он считается финальным.

При переопределении метода, также можно восстановить его старый код, в нужном для нас месте, за это отвечает слово super – что является ссылкой на базовый класс;
То есть в предыдущем примере, при переопределении методов, вместо строчек opened = true; и opened = false; можно написать слово super.Open() и super.Close(). Это позволит перенести весь код метода базового класса в наш переопределённый метод в нужное место.

Пример:
public class MatchBox extends Box
{
        public function MatchBox()
        {
                width = 15;
                height = 4;
                Open();
        }

        override public function Open():void
        {
                if(!oppened)
                {
                        width = width*2;
                }
                super.Open();
        }
        override public function Close():void
        {
                if(oppened)
                {
                        width = width/2;
                }
                super.Close();
        }
}


Так же при наследовании, всплывает наш старый знакомый — метод сокрития данных protected. Дело в том что если мы наследуем некие методы и свойства от некого класса, то мы сможем их увидить в классе потомке только если они будут иметь метод сокрытия public или protected.
Пример:
public class A
{
        public var x:Number = 10;
        private var y:Number = 20;
        protected var z:Number = 30;
        public function A()
        {}
}


Наследуем:
public class B extends A
{
        public function B()
        {
                x = -10; // Все работает!
                y = -20; // Получаем ошибку!
                z = -30; // Все работает!

                var objA:A = new A();
                objA.x = 100; // Все работает!
                objA.y = 200; // Получаем ошибку!
                objA.z = 300; // Получаем ошибку!
        }
}


Таким образом можна сказать что, privat — область видимости внутри класса, а protected — область видимости внутри класса и классах наследниках.

Это всё что касается наследования! Вот это и есть принципы Наследования и Полиморфизма.
Здесь я думаю тоже всё понятно.

Для заметки хочу сказать, что бывают ещё такие методы, свойства и константы как статические. Это значит, что для обращения к статическому методу класса не нужно создавать объект. Например, всем известный класс Math. Для того чтобы посчитать синус числа мы пишем Math.sin(30); То есть обращаемся к методу напрямую. Такой подход служит для создания независимых от объекта методов свойств и констант.
Пример:
public class SomeMath
{
        public static const PI:Number = 3.141592;
        public static var Num:Number = 10;
        public static function Factorial(n:int):int
        {
                var result:int = 1;
                for(var i:int =1; i<n+1; i++)
                {
                        result = result * i;
                }
                return result;
        }       
}


И применение:
public class MyClass
{
        public function MyClass()
        {
                var m:Number = SomeMath.PI;
                var n:Number = SomeMath.Factorial(4);
                SomeMath.Num = m;
        }
}

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

Теперь давайте поговорим о самом интересном, о том – что флеш делает флешом! Это конечно же события!
Что такое событие?
Пример. У нас есть кнопка, вот она у нас лежит, и тут в один прекрасный момент мы берём и нажимаем на неё! Вот событие и есть – «нажимаем»;

Объявление события состоит из двух частей:
1. Это само объявление (за него отвечает метод addEventListener).
2. Функция-хендл, которая представляется в виде обычного приватного метода с параметром, и запускается при срабатывании события. Хенд никогда ничего не возвращает.

Существует куча стандартных событий, они представлены в различных классах.
Для примера давайте напишем код для нашей коробки – чтобы она открывалась и закрывалась по клику мышки.

package
{
        import flash.display.MovieClip;
        import flash.events.MouseEvent;

        public class Box extends MovieClip
        {
                public var opened:Boolean = false;
                public function Box()
                {
                        addEventListener(MouseEvent.CLICK, OnMouseClick);
                }
                public function Open():void
                {
                        opened = true;
                }
                public function Close():void
                {
                        opened = false;
                }
                private function OnMouseClick(t:MouseEvent):void
                {
                        if (opened)
                        {
                                Close();
                        }
                        else
                        {
                                Open();
                        }
                }
        }
}


В данном случае у нас есть класс, который унаследован от класса MovieClip. В конструкторе класса объявлен слушатель на событие MouseEvent.CLICK. Таким образом, при нажатии мышкой на данный объект выполнится хендл OnMouseClick. Параметр е, который передаётся в хендл, содержит информацию о данном событии.

Для того чтобы отменить слушание события, используется метод removeEventListener.
Пример:
removeEventListener(MouseEvent.CLICK, OnMouseClick);


Также можно создавать свои события. За это отвечает метод dispatchEvent. Но о нём вы прочитаете самостоятельно.

Так же ООП существует понятия пакета, к которому относится класс. Слово package указывает папку, в которой лежит файл класса. В данном случае он лежит в одной папке с fla файлом. Но если наш класс будет лежать в папке source/boxes/ то пакет будет указываться так: package source.boxes. Конструкция package {} является обязательной.

Слово import указывает на то, что к нашему классу подключены другие классы, лежащие в других папках.
Пример:
import flash.display.MovieClip;


Вот наверное и все основы…

Теперь снова открываем браузер, набираем: http://ru.wikipedia.org/wiki/Объектно-ориентированное_программирование и внимательно читаем.

Есть понимание? Уже должно быть. Третий глаз начинает открываться, правда, старые 2 глаза закрываются! Шутка!
После тщательного прочтения умных вещей, давайте попробуем что-нибудь написать!
Да хоть тот самый коробок со спичками!

Для начала советую скачать программу Flash Develop и установите её. После этого открываем Flash, выбираем Flash File (ActionScript 3.0) и нажимаем Ок. Открываем установленный Flash Develop (FD) и нажимаем Projects->New Project. Выбираем в группе ActionScript 3.0 пункт Flash IDE Project, Задаем имя и сохраняем в той папке где и fla файл, созданный выше.
В правой части окна во вкладочке Project на проекте нажимаем правой кнопкой мыши на Add->NewClass. В открывшемся окне указываем имя класса (с большой буквы – для приличия) и если требуется, выбираем базовый класс, от которого будет наследоваться наш класс. В нашем случае MovieClip.

Создаём класс Box:

package{
        import flash.display.MovieClip;
        import flash.events.MouseEvent;

        public class Box extends MovieClip
        {
                public var opened:Boolean = false;
                public function Box()
                {}
                public function Open():void
                {
                        opened = true;
                }
                public function Close():void
                {
                        opened = false;
                }
        }
}


Рисуем наш спичечный коробок. Создаём из него объект MovieClip (F8). Внутри данного мувиклипа создаем 3 слоя. На первом создаём MovieClip крышку коробка. Называем её на как head. На втором слое рисуем 2 MovieClip-а по форме кнопок + и — , называем их на фрейме как btnPlus и btnMinus. На третьем слое рисуем прямоугольный MovieClip по всей форме нашего коробка, он будет служить контейнером для наших спичек. Назовём его на фрейме как conteiner. И оставляем на сцене.

Также рисуем картинку спички, делаем с неё MovieClip и удаляем со сцены.

Теперь напишем класс MatchBox наследующий наш класс Box. Это будет класс для нашего коробка и класс Match – спичка, наследуемый от класса MovieClip.

package{
        import flash.display.MovieClip;
        import flash.events.MouseEvent;

        public class MatchBox extends Box
        {
                public var btnPlus:MovieClip;
                public var btnMinus:MovieClip;
                public var conteiner:MovieClip;
                public var head:MovieClip;

                private var maxMatchCount:Number = 13;
                private var matchCount:Number = 0;
                private var matches:Array = new Array();

                public function MatchBox()
                {
                        head.addEventListener(MouseEvent.CLICK, OnHeadClick);
                }

                private function OnHeadClick(e:MouseEvent):void
                {
                        Close();
                        head.removeEventListener(MouseEvent.CLICK, OnHeadClick);
                        conteiner.addEventListener(MouseEvent.CLICK, OnConteinerClick);
                        btnMinus.addEventListener(MouseEvent.CLICK, OnBtnMinusClick);
                        btnPlus.addEventListener(MouseEvent.CLICK, OnBtnPlusClick);
                }

                private function OnConteinerClick(e:MouseEvent):void
                {
                        Open();
                        head.addEventListener(MouseEvent.CLICK, OnHeadClick);
                        conteiner.removeEventListener(MouseEvent.CLICK, OnConteinerClick);
                        btnMinus.removeEventListener(MouseEvent.CLICK, OnBtnMinusClick);
                        btnPlus.removeEventListener(MouseEvent.CLICK, OnBtnPlusClick);
                }

                private function OnBtnPlusClick(e:MouseEvent):void
                {
                        Add();
                }
                private function OnBtnMinusClick(e:MouseEvent):void
                {
                        Remove();
                }

                override public function Open():void
                {
                        head.y += head.height;
                        super.Open();
                }

                override public function Close():void
                {
                        head.y -= head.height;
                        super.Close();
                }

                public function Add():void
                {
                        if (matchCount <= maxMatchCount)
                        {
                                matchCount++;
                                var match:Match = new Match();
                                match.x = matchCount * 10;
                                match.y = 120;
                                conteiner.addChild(match);
                                matches.push(match);
                        }
                }

                public function Remove():void
                {
                        if (conteiner.numChildren > 1)
                        {
                                var obj:Object = conteiner;
                                conteiner.removeChild(matches.pop());
                                matchCount--;
                        }
                }
        }
}

package{
        import flash.display.MovieClip;

        public class Match extends MovieClip
        {

                public function Match()
                {}
        }
}


Теперь переходим в Flash IDE. Нажимаем Ctrl+L, в открывшемся окне находим клип нашего коробка и нажимаем на нём второй кнопкой, в открывшемся списке выбираем (в CS4) Properties (в CS3) Linkage. Ставим галочку на Export for ActionScript и в поле Class указываем класс MatchBox и нажимаем Ок. Аналогичное действие проводим с мувиком спички, указав класс Match.

Теперь нажимаем Ctrl+Shift+F12, в открывшемся окне выбираем вкладку Flash и на ней нажимаем кнопку Settings. В открывшемся окне убираем галочку с Avtomatically declare stage instance. Это позволит нам самостоятельно декларировать наши мувики в нашем же коде, что мы конечно уже сделали в классе MatchBox:
public var btnPlus:MovieClip;
public var btnMinus:MovieClip;
public var conteiner:MovieClip;
public var head:MovieClip;

Теперь тырцаем Ок, Ок. И пришол момент истенны: Ctrl+Enter. Смотрим что мы получили!

Вот примерно и всё… Дерзайте!

Комментарии (3)

0
И к слову хотелось бы заметить. Насколько я знаю, при импортировании стандортных классов типа flash.display.MovieClip — можно не париться и писать просто flash.display.*

Вроде бы при компиляции, забиваются только исопльзуемые классы. Или я не прав?
0
Лучше подключать только необходимые классы — будет уменьшаться время компиляции, хотя неиспользуемые классы не должны включаться. Надо будет проверить.

Для ФлешДевелопа есть плагин, или даже стандартная фича, которая удаляет неиспользуемые импорты.
0
import samples.*;
или
import samples.SampleCode;


В целом инструкции import должны быть максимально конкретизированы. Если планируется использовать только класс SampleCode из пакета samples, необходимо импортировать только класс SampleCode, но не весь пакет, к которому он принадлежит. Импорт всего пакета может привести к неожиданным конфликтам имен.

Это мнение Adobe! Я же подключаю пакеты полностью крайне редко. Да и наверное только тогда, когда эксперементирую. Например:
import fl.transitions.easing.*;

При использовании классов типа Tween.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.