Автор: Joey Lott [http://www.person13.com/]
В первых двух частях [часть 1 | часть 2] мы рассматривали структуру и синтаксис классов в ActionScript 2.0. Мы узнали, как создавать классы в ActionScript 2.0, включая использование пакетов, членов класса с разными режимами доступа (public/private/static), а также геттеров и сеттеров. Теперь поговорим о наследовании (inheritance) и интерфейсах (interfaces).
public/private/static
Наследование связано с иерархичностью классов. Можно определить подкласс и суперкласс. Подкласс автоматически наследует всех членов суперкласса без необходимости их явного повторного определения. Это важное и полезное свойство классов, поскольку позволяет использовать высокий уровень абстракции. А высокий уровень абстракции ведет к высокой эффективности рабочего процесса, и чем сложнее проект, тем это заметнее.
Например, вы хотите создать класс Car, подобный тому, что мы создавали в предыдущих частях статьи. Ясно, что Автомобиль — это один из многих типов Машины, помимо Автомобилей существуют Вертолеты, Дрезины, Джипы, Терминаторы и т.д. Хотя Машины и отличаются друг от друга, у них есть много общего. Все вышеперечисленные машины могут иметь такие свойства, как "грузоподъемность" или "пробег" (для Самолетов — "пролет"). А если Машина еще и передвигается в пространстве, у нее есть методы для перемещения с заданной скоростью.
Car
Так вот, если вы создадите суперкласс Vehicle (т. е. "Машина"), то можно в него поместить все общие для машин характеристики (свойства и методы). При этом код будет написан только в одном месте, а использовать его можно будет во многих местах: во всех подклассах класса Машины. Для создания суперкласса не нужно быть чемпионом по программированию среди домохозяек (или домохозяинов). Просто берете и создаете суперкласс, как раньше создавали обычные классы. А вот чтобы наследовать от этого класса (иными словами, расширить его), потребуются новая техника. Довольно легкая в освоении.
Vehicle
В терминах ООП можно сказать, что подкласс расширяет (extends) суперкласс. В нашем примере подкласс Car расширяет суперкласс Vehicle. Чтобы Flash создал такую связь между ними, нужно при объявлении подкласса использовать ключевое слово extends:
extends
В случае с Автомобилем и Машиной получится приблизительно следующее:
Вы всего один раз говорите, что класс Car расширяет класс Vehicle, и получаете при этом в свое распоряжение все свойства и методы класса Vehicle, как будто бы они были определены в классе Car.
Часто возникает ситуация, когда в подклассе необходимо унаследовать метод суперкласса без каких-либо изменений в этом методе. В таких случаях в определением подкласса просто не нужно ничего делать с этими методами. Но во многих других случаях метод суперкласса может быть перекрыт — для реализации в данном методе особенностей подкласса. Это называется перекрытием (overriding) метода суперкласса, поскольку при этом подкласс определяет в себе собственную реализацию метода, которая перекрывает унаследованную, родительскую.
Перекрывать методы суперкласса можно по-разному:
Чтобы полностью перекрыть родительский метод, просто определите в классе-потомке метод с точно таким же именем, как и у родительского метода. Например, если у суперкласса есть метод типа:
Потом можно определить реализацию метода в подклассе, которая перекроет реализацию этого метода в суперклассе:
Это был первый подход.
Если же вы хотите реализовать в подклассе метод, который будет вызывать также свою реализацию в суперклассе, можете использовать ключевое слово super, чтобы ссылаться на суперкласс и явно вызывать его метод из метода подкласса. Например, пример с методом display() в таком случае можно переписать следующим образом:
super
display()
Затем, если из экземпляра подкласса вызвать метод display() подкласса, в панели Output увидим следующее:
Ссылку super можно использовать в любом месте подкласса. Например, вызов super() будет ссылаться на метод конструктора суперкласса. Это пригодится, если вы хотите, чтобы конструктор подкласса выполнял некоторые действия, уникальные для подкласса, но в то же время вы хотите вызывать конструктор суперкласса, передавая ему некие конкретные значения. Единственное предостережение: конструктор суперкласса должен всегда вызываться в первой строке конструктора подкласса, если вы вызываете его явно. В противном случае получите ошибку компиляции.
super()
Конец теории. Выполним упражнение. Создадим суперкласс Vehicle (Машина) и подкласс Car (Автомобиль). Если вы сделали упражнение из второй части данной статьи, то вам будет легко следить за мыслью.
Niva
Kukuruzniq
Plane
Интерфейсы — это просто. Это набор правил, в соответствии с которыми реализуется некий набор классов. Когда вы определяете класс, который следует правилам интерфейса, то говорят, что класс реализует (иногда на жаргоне говорят — "имплементит", от англ. "implements") интерфейс.
Какие правила определяются в интерфейсе? Интерфейс в ActionScript 2.0 сообщает Flash, какие методы должны реализоваться в классе, включая следующую информацию:
private
static
В интерфейсе недопустимы:
Затем можно реализовывать интерфейс в классе. При этом, кроме всего прочего, в классе должны реализовываться методы, объявленные в интерфейсе. В противном случае на этапе компиляции Flash выдаст сообщение об ошибке.
Не все разработчики схватывают на лету плюсы интерфейсов. На первый взгляд кажется, что это только лишняя неблагодарная работа. Ведь в самом интерфейсе нет функциональности, потому что в нем нет реализаций объявляемых в нем же методов.
Реальное величие интерфейсов видится с некоторого расстояния. если вы создаете один класс для одного приложения, то интерфейсы вам и не нужны. И не все классы обязаны реализовать интерфейс. Но если вы работаете в команде, а проект не маленький — тут интерфейсы приходят на выручку, помогая создавать основные вехи проекта, что повышает эффективность процесса не только на этапе разработки иерархии классов приложения, но также и на этапе применения этих классов.
Например, вы работаете в команде, которая создает классы Vehicle (Машина), Animal (Животное), Wind (Ветер) и Planet (Планета). В то время как у каждого из этих классов может быть собственный API, между ними есть и общее — все они способны двигаться. Если вы хотите реализовать движение в каждом из этих классов, можно создать интерфейс IMoveable, который будет реализовываться всеми этими классами. Интерфейс IMoveable будет содержать объявление метода move(), так что теперь каждый конкретный человек, работающий над реализацией конкретного класса, будет учитывать этот факт в процессе разработки и реализует метод move() в разрабатываемом им классе. Это большой плюс при командной работе. Когда вы создаете интерфейс и определяете, какие классы будут его реализовать, то потом все разработчики, работающие над классом, будут заранее знать, какие методы писать, и это облегчает стандартизацию API всех классов. Еще одно преимущество получает разработчик, использующий такой класс. Зная, какой именно конкретный интерфейс реализуется в классе, вы ужен знаете много о своем API.
Animal
Wind
Planet
IMoveable
move()
Один класс может реализовывать многочисленные интерфейсы. Поэтому интерфейсы часто используются как форма множественного наследования в языках, изначально не поддерживающих такой вид наследования. В ActionScript подкласс может наследовать только от одного суперкласса. Например, класс Car расширяет класс Vehicle, и следовательно не может расширять ни один другой класс. Но Car может реализовывать множественные интерфейсы (продолжая при этом наследовать от класса Vehicle.) Например, Car может реализовать интерфейсы типа IDrivable (автомобиль можно водить), IManufacturable (можно производить), ISellable (можно продать).
IDrivable
IManufacturable
ISellable
Рассмотрим пример объявления и определения интерфейса. Вы уже знаете синтаксис и структуру классов, так что нового здесь будет совсем немного.
Декларация (объявление) интерфейса выглядят почти идентично декларации класса. Единственное различие в том, что при объявлении интерфейса используется ключевое слово interface, вместо ключевого слова class. Например:
interface
class
В интерфейсе можно только объявлять методы, но не реализовывать их. Реализовываться методы будут в классах, реализующих интерфейс. В интерфейсе нельзя также объявлять свойства. Еще раз кратко перечислим то, что может и должно содержаться в интерфейсе:
Вот пример готового интерфейса IMoveable:
Как и классы, интерфейсы удобно хранить в пакетах. Например, можно упаковать IMoveable в пакет com.person13. В декларации интерфейса это выглядит вот так:
И также, как и классы, интерфейсы могут расширять друг друга Например, IDrivable может расширять IMoveable, вот как будет при этом выглядеть код:
После определения интерфейса можно указать, что некий класс реализует этот интерфейс. Для этого используется ключевое слово implements, за которым будет следовать список разделенных запятыми реализуемых интерфейсов. Например, если класс Vehicle реализует интерфейс IMoveable, то начало объявления класса будет выглядеть так:
implements
Конечно, при этом можно пользоваться импортом (как и с классами):
А вот класс Car реализует интерфейсы IDrivable, IManufacturable, и ISellable:
Когда класс реализует интерфейс, Flash будет проверять правильность этой реализации во время компиляции. И если какой-то метод пропущен или объявлен неверно, не так, как в интерфейсе, то Flash выдаст сообщение об ошибке.
Вот и разобрались. Комментарии приветствуются как никогда. Спасибо :]
1) Часто вместо "перекрытие" говорят "переопределение". Пусть это вас не смущает!
2) Не забывайте, что иногда вместо "реализовать" говорят "имплементить".
Огромное спасибо! Очень хорошие материалы. С уважением и пожеланиями
Рост, англицизм "имплементит" если и используют, то не часто. Вообще не понимаю зачем использовать такие уродливые кальки тогда, когда есть нормальный (и общеупотребительный, кстати)русскоязычный эквивалент слову "implements".
Wow! Не знаю что должно сказать! Очень очень спасибо :) Золотые материалы. С уважением!
2Max:
Я подумал и решил, что действительно можно обойтись без жаргона. Оставил примечание. Спасибо!
2Рост: Как мне заставить подкласс Car расширять суперкласс Vehicle и имплементить интерфейс IDrivable одновременно ( то есть в одном строке )?
Спасибо заранее :)
Hello!
Опечатка у переводчика или автора: "...Это был первый подход. Если же вы хотите реализовать в подклассе метод, который будет вызывать также свою реализацию в подклассе, можете использовать ключевое слово super..."
Вместо последнего слова "подклассе" д.б. слово "суперклассе".
2Смольный: Спасибо за замечание, ошибку исправил!
Спасибо, зачитал все три статьи. Если бы не они, так бы и думал, что программирование даже на новом флеше - полная задница :)
Спасибо но еслибы была рассылка статей на почту былобы ещё круче
Рассылку новостей сделаем. В ближайшем будущем.
а теперь ваще умный стал