четверг, 15 апреля 2010 г.

Полиморфизм через Интерфейсы

Интерфейсы в ActionScript 3.0 являются очень мощным средством как для полиморфизма так и для ООП и паттернов проектирования (Design Patterns) вместе взятых.

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

И так, интерфейс — это набор объявлений методов, который позволяет несвязанным объектам взаимодействовать друг с другом.

Структура определения интерфейса похожа на структуру определения класса за тем исключением, что интерфейс может содержать только методы без тел. Интерфейсы не могут содержать переменных или констант, но могут включать функции get и set. Для определения интерфейса используется ключевое слово interface. Например, следующий интерфейс, IExample.
Интерфейс IExample определяет протокол для сериализации объекта, то есть для преобразования объекта в формат, пригодный для хранения на устройстве или для транспортировки по сети.

public interface IExample
{
function writeExternal(input:String):void;
function readExternal():String;
}

Обратите внимание на то, что интерфейс IExample объявляется с использованием модификатора управления доступом public. Определения интерфейса могут модифицироваться только с использованием атрибутов public и internal. Объявления методов внутри определения интерфейса не могут иметь модификаторов управления доступом.
В ActionScript 3.0 используется правило именования интерфейсов с заглавной буквы I, однако в качестве имени интерфейса можно использовать любой допустимый идентификатор. Определения интерфейсов часто помещаются в верхнем уровне пакета. Определения интерфейсов нельзя помещать внутри определения класса или определения другого интерфейса.
Интерфейс может расширять один или несколько других интерфейсов. Например, следующий интерфейс IExtendExample расширяет интерфейс IExample.

public interface IExtendExample extends IExample
{
function extra():void;
}

Любой класс, внедряющий интерфейс IExtendExample, должен включать реализации не только для метода extra(), но также методы writeExternal() и readExternal(), унаследованные от интерфейса IExample.

package
{

public class CurrentExample extends Sprite implements IExtendExample
{

private var str:String;

public function CurrentExample (){}

public function writeExternal(input:String):void
{
this.str = input;
}

public function readExternal():String
{
return this.str;
}

public function extra():void{}
}
}

Давайте рассмотрим конкретный пример на реализации Паттерна ADAPTER!!!!
Первый класс Adaptee, который предоставляет нам основные функции для работы, которые в дальнейшем могут быть переписаны из класса наследника.

package
{
public class Adaptee
{
public function specificRequest( ):void
{
trace("Вызван Adaptee:specificRequest( )");
}
}
}

Реализация интерфейса...

package
{
public interface ITarget
{
function request( ):void
}
}

Наш основной класс который реализует интерфейс ITarget, обратите внимание на то что класс обязательно должен реализовать по крайнем мере одну или все функции предоставленные реализуемым интерфейсом:
package
{
public class Adapter implements ITarget
{
private var adaptee:Adaptee;
public function Adapter()
{
this.adaptee = new Adaptee();
}
public function request():void
{
adaptee.specificRequest( );
}
}
}

Ну и конечно же наш клиент, который является документ классом для приложения
package
{
import flash.display.MovieClip;
/**
* Main Class
* Документ класс для флеша
*/
public class Main extends MovieClip
{
public function Main( )
{
var target:ITarget = new Adapter( );
target.request( );
}
}
}

Клиент класс создает экземпляр класса Adapter и вызывает метод request( ) реализуемый интерфейсом ITarget. Клиент видит только функции интерфейса реализумого через Adapter класс, что дает нам хорошую гибкость в использвани объектов и их методов!
Adapter класс держит жесткий контроль доступа к существующему классу, осуществляя только интерфейс ITarget! Клиент же не должен знать о том что адаптер использует существующий класс. Так как класс Adapter создает экземпляр класса Adaptee, то между ними налаживается связь. Это не позволяет Adapter использовать подкласс Adaptee, т.е. расширять его или использовать полностью различный существующий класс, не изменяя существующий код Adaptor.

Можно было бы немного изменить класс Adapter добавив параметр в конструктор пердающий ссылку на объект Adaptee, чтобы мы могли обращаться к нему из документ класса. Хотя этот метод и не дает никаких видимых приемущест за исключеением того что можно обращаться и к экземпляру класса Adaptee... следующий пример показывает как это реализовать:

public function Adapter(a:Adaptee)
{
this.adaptee = a;
}

И в Main меняем на
public function Main( )
{
var adaptee:Adaptee = new Adaptee( );
var target:ITarget = new Adapter(adaptee);
target.request( );
}

Теперь мы можем оперировать методами и свойствами Adaptee класса из документ класса!!!))

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

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

вторник, 6 апреля 2010 г.

Абстрактные классы - быть или не быть?

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

package
{
//Абстрактный класс
public class AbstractClass
{
function abstractMethod( ):void {}
function concreteMethod( ):void
{
trace("ПРИВЕТ! Я метод из абстрактного класса)")
}
}
}


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

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


package
{
//Подкласс абстрактного класса
public class Subclass extends AbstractClass
{
override function abstractMethod( ):void
{
trace("ЭТО переписанный метод абстрактного класса");
}
}
}

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

package
{
//Осуществление подкласса абстрактного класса
import flash.display.Sprite;
public class ImplementSub extends Sprite
{
// как мы видим тип переменной абстрактен, и мы никогда не сможем создать экземпляр данного типа
private var doDemo:AbstractClass;
public function ImplementSub( )
{
// зато мы можем создать экземпляр подкласса и получить доступ ко всем метода родителя
doDemo=new Subclass( );
doDemo.abstractMethod( );
doDemo.concreteMethod( );
}
}
}


Сохраните пример как ImplementSub.as и сделайте его документ классом, после этого запустите компилятов...в строке аутпута будет следующее:

---ЭТО переписанный метод абстрактного класса----
---ПРИВЕТ! Я метод из абстрактного класса)-----


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

Богатые Интернет Приложения

Добрый день!!!)
Первый пост я бы хотел посвятить, так сказать, введению о том, что же такое RIA и с чем его едят.
RIA - RICH INTERNET APPLICATIONS - это приложение, доступное через Интернет, богатое функциональностью традиционных настольных приложений, не поддерживаемой браузерами непосредственно. Как правило, приложение RIA:

* передаёт веб-клиенту необходимую часть пользовательского интерфейса, оставляя большую часть данных (ресурсы программы, данные и пр.) на сервере;
* запускается в браузере и не требует дополнительной установки ПО;
* запускается локально в среде безопасности, называемой «песочница» (sandbox).

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

* Не требуется установка приложения; обновление и распространение приложения — быстрый и автоматизированный процесс
* Обновление версий автоматическое
* Пользователи могут использовать приложение на любом компьютере, имеющем соединение с Интернет, причем обычно неважно, какая операционная система на нём установлена
* При работе веб-приложения компьютер пользователя гораздо меньше подвержен вирусному заражению, чем при запуске exe-файлов.

Поскольку RIA используют движок клиента для взаимодействия с пользователем, они:

* Богаче. RIA предлагают пользовательский интерфейс, не ограниченный лишь использованием языка HTML, применяемого в стандартных веб-приложениях. Расширенная функциональность позволяет использовать такие возможности пользовательского интерфейса, как drag-and-drop, использование ползунка для изменения данных, а также возможность производить вычисления, которые не отправляются обратно на сервер, а выполняются прямо на машине пользователя (например, ипотечный калькулятор).
* Более интерактивные. Интерфейсы RIA более интерактивны, чем стандартные интерфейсы веб-браузеров, которые требуют постоянного взаимодействия с удалённым сервером.
* Наиболее сложные приложения RIA предлагают внешний вид и функциональность, близкие к настольным приложениям. Использование движка клиента позволяет добиться и других преимуществ в производительности:
* Сбалансированность клиент-сервера. Использование вычислительных ресурсов клиента и сервера лучше сбалансировано. Поэтому сервер не должен быть «рабочей лошадкой», как в традиционных веб-приложениях. Это освобождает вычислительные ресурсы сервера, позволяя обрабатывать большее количество сессий одновременно за счёт одного и того же аппаратного обеспечения.
* Асинхронная коммуникация. Движок клиента может взаимодействовать с сервером, не дожидаясь, пока пользователь совершит действие в приложении, нажав на кнопку или ссылку. Это позволяет пользователю просматривать страницу и взаимодействовать с ней асинхронно с помощью коммуникации между движком и сервером. Эта возможность позволяет разработчикам RIA передавать данные между клиентом и сервером без ожидания пользователя. В Google Maps эта техника используется для того, чтобы подгружать прилегающие сегменты карты, прежде чем пользователь пролистает, чтобы их посмотреть.