
Основы ООП для ActionScript 3.0

Решил выложить свою старую статью, которую готовил для тематической группы Вконтакте. Для многих данная статья, не откроет ничего нового, так как здесь описаны фундаментальные вещи объектно-ориентированного программирования в ActionScript 3.0 и рассчитана для самых маленьких. Надеюсь для мира она будет полезна =)
Конечно лектор из меня никудышный, так что сильно не гнобите если что…
Приступим. Первое что приходит в голову – это что такое объектно-ориентированное программирования. Открываем браузер, набираем: http://ru.wikipedia.org/wiki/Объектно-ориентированное_программирование и внимательно читаем.
Если вы ничего не поняли с выше прочитанного – это нормально!
Как сказано на странице Википедии, ООП базируется на объектах и соответствующих им классах.
Значит класс, что это и с чем его едят. Классом можно назвать описания типа данных. Т.е. такие вещи как MovieClip, Button это тоже классы.
Класс описывает внутреннее строения объекта, все его свойства и функции.
Например, у нас есть коробка спичек. Что мы можем о ней сказать? Она имеет определённый размер: длинна, ширина, высота, она имеет определённый цвет: серый, она имеет определённый текст (реклама на задней стороне коробки), она имеет внутри определённое количество спичек. Также можно сказать, что коробка может выполнять некоторые функции, например: открываться и закрываться. Примерно так мы представляем эту коробку в реальном мире!
Для того чтобы описать нашу коробку языком ООП давайте разберёмся с некоторыми определениями.
Свойство – являет собой переменную некого конкретного типа.
Метод – функция выполняющая определённое действие. Может принимать параметры, а может, и нет. Может возвращать какие-то данные, а может, и нет.
Данную коробку можно описать в классе. Пример:
Название класса: коробка
Свойства: ширина, высота, длинна, цвет, текст, количество спичек.
Методы: Открываться, закрываться.
Представим это в коде:
class Box
{
var width:Number = 10;
var height:Number = 10;
var depth:Number = 10;
var text:String = "Реклама";
var color:Number = 0x000000;
var matchCount:int = 3;
function Box()
{}
function Open():void
{
}
function Close():void
{
}
}
Получаем что-то в этом роде. Не спешите это всё писать.
Если внимательно посмотреть на полученный код, то можно заметить что у нас есть метод, который имеет такое же название, как и сам класс. Этот метод называется конструктор, и служит для инициализации объекта, который описывается данным классом. Если в вашем коде метод-конструктор отсутствует, то он будет создан автоматически при компиляции.
Замечание: Хорошим тоном программирования считается написание имен классов и методов с большой буквы. Имена свойств с маленькой. Также приветствуется написание всех идентификаторов (имен) в смысловом значении, без всяких знаков подчёркивания итд. Пример: MamaMilaRamu а не Mama_mila_ramu, MyNameIs а не My_nameis. Такой подход улучшает читабельность кода.
Давайте для наглядности создадим ещё один класс – спичка:
class Match
{
var length:Number = 10;
var color:Number = 0xffffff;
var burned:Boolean = false;
function Match()
{}
function Burn():void
{
burned = true;
}
}
Я думаю, что значения свойств и методов данного класса объяснять не нужно.
Таким образом, мы имеем 2 класса Box и Match.Попробуем создать в классе Box, объект Match. Перепишем наш класс Box:
class Box
{
var width:Number = 10;
var height:Number = 10;
var depth:Number = 10;
var text:String = "Реклама";
var color:Number = 0x000000;
var matchCount:int = 1;
var match:Match = new Match();
function Box()
{
}
function Open():void
{
}
function Close():void
{
}
}
Создаём новое свойство(переменную), указываем тип Match – наш класс, и присваиваем ему новый объект Match. Этот процесс присваивания называется инициализация нового объекта. За инициализацию отвечает директива new. Если взглянуть на данный процесс внутри памяти компа, то мы увидим, как под переменную match выделяется память нужного размера, в неё помещаются все наши свойства и описания методов, и запускается метод. Таким образом рождается новый объект. Если мы объявляем нашу переменную, но не инициализируем ее, то в памяти под нее отводится место, но никаких свойств, методов там нет. И соответственно конструктор в данном случае не запускается. Значение такой переменной является null, или же пустота.
После проделанного, мы можем работать с объектом match, задавая новые значения его свойствам и запуская его методы.
Методы могут принимать параметры и возвращать некие данные – результат роботы метода.
Пример:
function Add(mane:String):void // принимает параметр mane типа String
{
}
Или же:
function Sum(a:Number, b:Number):Number //принимает 2 параметра, суммирует и возвращает суму
{
return a+b;
}
Слово return служит для возвращения результатов работы метода.
Если же мы объявляем метод, который будет возвращать какие-либо данные, нам нужно указать тип этих данных. В противном случае указывается тип void, который значит, что ничего возвращать не будем.
Также хочу заметить – в ООП ТИПИЗАЦИЯ ДАННЫХ ЯВЛЯЕТСЯ ОБЕЗАТЕЛЬНОЙ!
Теперь давайте поговорим о зоне видимости наших классов, свойств и методов.
В ООП, существует возможность скрывать методы и свойства, то есть, задавать зону видимости:
Public – позволяет объявить публичный (открытый для всех) метод или свойство.
Private – позволяет объявить внутренний (закрытый для всех, кроме самого себя) метод или свойство.
Protected – позволяет объявить внутренний метод или свойство, но его можно будет увидеть при наследовании класса (о наследовании немного ниже).
Как это работает, например, в нашем классе Match, есть свойство color и мы хотим чтобы к данному свойству нельзя было добраться снаружи. Для этого нам нужно объявить его как приватное (private). Если же нам нужно создать свойство, доступ к которому мог осуществляться извне, то мы объявляем публичное (public) свойство. Если же видимость не задана, то свойство или метод по умолчанию считаются приватными.
Вот пример нашего класса Match:
public class Match
{
public var length:Number = 10;
public var color:Number = 0xffffff;
public var burned:Boolean = false;
public function Match()
{}
public function Burn():void
{
burned = true;
Light();
}
private function Light():void
{
//код метода
}
}
В данном случае, метод Light, является приватным, это означает, что мы не можем его вызвать из класса Box, но можем вызвать в классе Match.
class Box
{
public var width:Number = 10;
public var height:Number = 10;
public var depth:Number = 10;
public var text:String = "Реклама";
public var color:Number = 0x000000;
public var matchCount:int = 1;
public var match:Match = new Match();
public function Box()
{}
public function Open():void
{
}
public function Close():void
{
}
public function LightMach():void
{
match.Light(); // вызовет ошибку, так как метод Light() является приватным, и невидимым извне.
match.Burn(); // запустит метод Burn() объекта match, так как он является публичным, и его можно увидеть извне.
}
}
Ещё существует такое понятие как ссылка на самого себя – this; Что это значит? Объясняю. Иногда нужно внутри метода создать переменную с определённым именем, но в нашем классе существует свойство, которое уже имеет такое имя – в таком случае нам на выручку приходит ссылка на самого себя.
Пример:
public class Match
{
public var length:Number = 10;
public var color:Number = 0xffffff;
public var burned:Boolean = false;
public var x:Number = 10;
public function Match()
{}
public function Burn():void
{
burned = true;
Light();
}
private function Light():void
{
var x:Number;
x = 30; // присваеваем значение 30 переменной x.
this.x = 25; // присваеваем значение 24 свойчтву public var x:Number
}
}
В данном примере использование слова this понадобилось исключительно, для того чтобы обратится не к переменной x а к свойству x объявленном в начале класса.
Также конструкция this служит для передачи данного объекта (самого себя) как параметра методу другого объекта.
Вот это и есть Абстракция и Инкапсуляция. Это понятно?
Теперь давайте поговорим о наследовании. Принцип наследования в ООП, аналогичен принципу наследования в нашей жизни. Ой смотрите у него папины глаза, а у неё мамин нос! Так можно сказать и в программировании.
Например у нас есть класс Box – коробка (упростим для примера наш старый Box):
public class Box
{
public var width:Number;
public var height:Number;
public var depth:Number;
public var opened:Boolean = false;
public function Box()
{
}
public function Open():void
{
opened = true;
}
public function Close():void
{
opened = false;
}
}
Этот класс описывает основные свойства всех коробок в мире! То есть такое же поведение будет иметь и коробка от обуви, и от телевизора, и от холодильника. Неправда ли?
Но нам, например, нужно описать коробку для спичек и коробку для обуви и чтобы не заниматься одной и той же работой дважды, мы используем наследование. Например, выше приведённый класс Box будем считать базовым классом, и породим от него 2 класса: MatchBox и ShoesBox. Для этого нам нужно использовать при объявлении этих классов слово extends, которое указывает, что данный класс является наследником другого класса.
Пример:
public class MatchBox extends Box
{
public function MatchBox()
{}
}
И
public class ShoesBox extends Box
{
public function ShoesBox ()
{}
}
Эти оба класса унаследовали от класса Box все его свойства и методы. То есть мы можем свободно ними пользоваться как своими.
Пример:
public class MatchBox extends Box
{
public function MatchBox()
{
width = 15;
height = 4;
Open();
}
}
Или
public class ShoesBox extends Box
{
public function ShoesBox()
{
}
private function Preview():void
{
Open();
}
}
Но бывают случаи, когда нас тот или же иной метод, унаследованный от базового класса, не устраивает, и мы бы хотели его изменить. Этот процесс называется — переопределение метода, и заключается в переписывании метода с указанием слова override.
Пример:
public class MatchBox extends Box
{
public function MatchBox()
{
width = 15;
height = 4;
Open();
}
override public function Open():void
{
if(!oppened)
{
width = width*2;
}
opened = true;
}
override public function Close():void
{
if(oppened)
{
width = width/2;
}
opened = false;
}
}
Продолжение
- +10
- mousexaker
Комментарии (28)
Советую все-таки почитать соглашения по написанию кода, дабы не вводить самых маленьких в заблуждение:
Лучше mamaMilaRamu, а не MamaMilaRamu
Почему-то не люблю методы с заглавной.
Хотя часто по привычке использую подчеркивание ball_mc (раньше (as2) помогало подхватывать методы)
Но компромисным вариантом считаю — придерживаться хоч чего нибудь =)
Что-нибудь лучше чем ничего ;) Но лучше что-то универсальное.
Вы место экономите? ;)))
Впрочем это дело предпочтений, я не воспринимаю фигурную скобу на той же строке, просто ее не замечаю сразу, приходится потом сопоставлять.
Но есть некоторые моменты:
— автор умолчал о пакетах;
— как-то выпал операнд доступа internal (доступ только из своего пакета), а ведь он является операндом по-умолчанию — если ничего не писать перед методом, то будет использоваться именно он;
— всё-таки не стоит принцип наследования называть наследственностью. ИМХО это «две большие разницы».
— как-то туманно описано применение this. Точнее было-бы сказать: если в методе есть локальная переменная с тем же именем, что и существующая глобальная переменная (свойство экземпляра класса), то локальная затеняет глобальную переменную. Для обращения к глобальной переменной нужно писать this.имяПеременной, для обращения к локальной просто имяПеременной
Ну естественно, это мое мнение, на переделке не настаиваю =)
Операнд internal — сорри, неучел. (Я ним просто никогда не пользуюсь)
По поводу наследственности — согласен, не правильно выбрал слово =)
Всё же, логичнее про них упомянуть сразу — вместе с операндами доступа. Вот начнете Вы сейчас вписывать про internal и волей-неволей скажете о них )