Programação orientada a objetos no ActionScript


Este post descreve os elementos do ActionScript que oferecem suporte à OOP (Programação orientada a objetos).
O capítulo não descreve princípios de OOP gerais, como design de objeto, abstração, encapsulamento, herança e
polimorfismo. Ele se concentra em como aplicar esses princípios usando o ActionScript 3.0.
Devido a raízes do ActionScript como uma linguagem de script, o suporte ao OOP do ActionScript 3.0 é opcional. Isso
fornece aos programadores flexibilidade para escolherem a melhor abordagem para projetos de vários escopos e
complexidades. Para tarefas pequenas, você pode chegar à conclusão de que usar o ActionScript com um paradigma
de programação de procedimento é tudo o que você precisa. Para projetos maiores, aplicar princípios de OOP pode
fazer com que o código fique mais fácil de ser compreendido, mantido e estendido.
Noções básicas de programação orientada a objetos
Introdução à programação orientada a objetos
OOP (Programação orientada a objetos) é uma maneira de organizar o código em um programa agrupando-o em
objetos, elementos individuais que incluem informações (valores de dados) e funcionalidade. O uso de uma abordagem
orientada a objetos para organizar um programa permite agrupar partes específicas de informações (por exemplo,
informações sobre música, como título do álbum, título da faixa ou nome do artista) juntamente com a funcionalidade
comum ou com as ações associadas a essas informações (como “adicionar faixa à lista de reprodução” ou “reproduzir
todas as canções desse artista”). Esses itens são combinados em único item, um objeto (por exemplo, um “Album” ou
“MusicTrack”). Vários benefícios são obtidos quando se pode agrupar esses valores e funções em conjunto, incluindo
apenas a necessidade de manter o rastreio de uma única variável, em vez de várias, organizar a funcionalidade
relacionada em conjunto, e poder estruturar programas de maneiras muito correspondentes ao mundo real.
Tarefas de programação orientadas a objetos comuns
Na prática, a programação orientada a objetos tem duas partes. Uma parte são as estratégias e técnicas para criar um
programa (freqüentemente chamada de design orientado a objetos). Esse é um assunto abrangente e não é discutido
neste capítulo. A outra parte da OOP são as estruturas reais de programação que estão disponíveis em uma
determinada linguagem de programação para criar um programa usando uma abordagem orientada a objetos. Este
capítulo abrange as seguintes tarefas comuns na OOP:
• Definição de classes
• Criação de propriedades, métodos e obtenção e definição de acessor (métodos de acessor)
• Controle do acesso a classes, propriedades, métodos e acessores
• Criação de propriedades e métodos estáticos
• Criação de estruturas semelhantes a enumeração
• Definição e uso de interfaces
• Trabalho com herança, incluindo substituição de elementos de classes

Conceitos e termos importantes
A lista de referência a seguir contém termos importantes usados neste post:
• Atributo: Uma característica atribuída a um elemento de classe (como uma propriedade ou método) na definição
de classe. Os atributos são usados normalmente para definir se a propriedade ou método estará disponível para
acesso por código em outras partes do programa. Por exemplo, private e public são atributos. Um método
particular pode ser chamado apenas pelo código dentro da classe, enquanto um método público pode ser chamado
por qualquer código no programa.
• Classe: A definição da estrutura e o comportamento de objetos de um determinado tipo (como um modelo ou
plano gráfico de objetos desse tipo de dados).
• Hierarquia de classes: A estrutura de várias classes relacionadas, especificando a classes que herdam funcionalidade
de outras classes.
• Construtor: Um método especial que você pode definir em uma classe, que é chamado quando uma ocorrência da
classe é criada. Um construtor é usado normalmente para especificar valores padrão ou, de outra forma, executar
operações de configuração do objeto.
• Tipo de dados: O tipo de informações que uma variável específica pode armazenar. Em geral, tipo de dados tem o
mesmo significado que classe.
• Operador ponto: O sinal de ponto (.), que no ActionScript (e em muitas outras linguagens de programação) é
usado para indicar que um nome faz referência a um elemento filho de um objeto (como uma propriedade ou
método). Por exemplo, na expressão myObject.myProperty, o operador ponto indica que o termo myProperty
está fazendo referência a algum valor que é um elemento do objeto denominado myObject.
• Enumeração: Um conjunto de valores constantes relacionados, agrupados em conjunto por conveniência como
propriedades de uma única classe.
• Herança: O mecanismo da OOP que permite que uma definição de classe inclua toda a funcionalidade de uma
definição de classe diferente (e geralmente seja adicionada a essa funcionalidade).
• Ocorrência: Um objeto real criado em um programa.
• Espaço para nomes: Essencialmente um atributo personalizado que permite controle mais refinado sobre qual
código pode acessar outro código.
Teste dos exemplos do post
Talvez você queira testar algumas das listagens de código de exemplo por si próprio, durante a leitura deste capítulo.
Como as listagens de código neste capítulo tratam principalmente com a definição e a manipulação de tipos de dados,
testar os exemplos envolve a criação de uma ocorrência da classe que está sendo definida, a manipulação dessa
ocorrência usando suas propriedades ou métodos e a exibição dos valores das propriedades dessa ocorrência. Para
exibir esses valores, grave-os em uma ocorrência do campo de texto no Palco ou use a função trace() para imprimir
valores no painel Saída.

Classes
Uma classe é uma representação abstrata de um objeto. Uma classe armazena informações sobre os tipos de dados que
um objeto pode manter e os comportamentos que um objeto pode exibir. A utilidade dessa abstração pode não ser
aparente quando você grava pequenos scripts que contêm apenas alguns objetos que interagem entre si. No entanto,
conforme o escopo de um programa aumenta, assim como o número de objetos que precisam ser gerenciados, você
pode descobrir que as classes permitem um controle melhor de como os objetos são criados e como eles interagem
entre si.
Já no ActionScript 1.0, os programadores do ActionScript podiam usar objetos Function para criar construções
semelhantes a classes. O ActionScript 2.0 adicionou suporte formal para classes com palavras-chave, como class e
extends. O ActionScript 3.0 não apenas continua a oferecer suporte às palavras-chave introduzidas no ActionScript
2.0, mas também adiciona alguns novos recursos, como controle de acesso aprimorado com os atributos protected
e internal, e melhor controle sobre a herança com as palavras-chave final e override.
Se você já tiver criado classes em linguagens de programação, como Java, C++ ou C#, descobrirá que o ActionScript
fornece uma experiência familiar. O ActionScript compartilha muitas das mesmas palavras-chave e nomes de
atributos, como class, extends e public, que são discutidos nas seções a seguir.
Nota: Neste capítulo, o termo propriedade significa qualquer membro de um objeto ou classe, incluindo variáveis,
constantes e métodos. Além disso, embora os termos classe e estática sejam sempre usados alternadamente, neste capítulo
esses termos são distintos. Por exemplo, neste capítulo a expressão propriedades de classes fazem referência a todos os
membros de uma classe, em vez de apenas a membros estáticos.
Definições de classes
As definições de classes do ActionScript 3.0 usam sintaxe semelhante a usada no ActionScript 2.0. A sintaxe apropriada
para uma definição de classe requer a palavra-chave class seguida pelo nome da classe. O corpo da classe que está
entre chaves ({}) segue o nome da classe. Por exemplo, o código a seguir cria uma classe denominada Shape que
contém uma variável denominada visible:
public class Shape
{
var visible:Boolean = true;
}
Uma alteração significativa na sintaxe envolve definições de classes que estão dentro de um pacote. No ActionScript
2.0, se uma classe estiver dentro de um pacote, o nome do pacote deverá estar incluído na declaração da classe. No
ActionScript 3.0, que introduz a instrução package, o nome do pacote deve estar incluído na declaração do pacote em
vez de na declaração da classe. Por exemplo, as seguintes declarações de classe mostram como a classe BitmapData,
que faz parte do pacote flash.display, é definida no ActionScript 2.0 e no ActionScript 3.0:
// ActionScript 2.0
class flash.display.BitmapData {}
// ActionScript 3.0
package flash.display
{
public class BitmapData {}
}
Atributos de classes
O ActionScript 3.0 permite modificar definições de classe usando um dos quatro seguintes atributos:

Sem título3

Para cada um desses atributos, exceto para internal, você deve incluir explicitamente o atributo para obter o
comportamento associado. Por exemplo, se você não incluir o atributo dynamic ao definir uma classe, não poderá
adicionar propriedades a uma ocorrência da classe em tempo de execução. Você atribui explicitamente um atributo
colocando-o no início da definição de classe, conforme demonstrado no código a seguir:
dynamic class Shape {}
Observe que a lista não inclui um atributo denominado abstract. Isso é porque as classes abstratas não têm suporte
no ActionScript 3.0. Observe também que a lista não inclui atributos denominados private e protected. Esses
atributos têm significado apenas dentro de uma definição de classe e não podem ser aplicados às próprias classes. Se
você não desejar que uma classe seja publicamente visível fora de um pacote, coloque-a no pacote e marque-a com o
atributo internal. Como alternativa, você pode omitir os atributos internal e public e o compilador adicionará
automaticamente o atributo internal para você. Para que uma classe seja visível fora do arquivo de origem no qual
ela está definida, coloque a classe na parte inferior do arquivo de origem, abaixo das chaves de fechamento de definição
do pacote.
Corpo da classe
O corpo da classe, que é delimitado por chaves, é usado para definir as variáveis, constantes e métodos da classe. O
exemplo a seguir mostra a declaração da classe Accessibility na API do Adobe Flash Player:
public final class Accessibility
{
public static function get active():Boolean;
public static function updateProperties():void;
}
Você também pode definir um espaço para nomes dentro de um corpo de classe. O exemplo a seguir mostra como um
espaço para nomes pode ser definido dentro de um corpo de classe e usado como atributo de um método naquela
classe:
public class SampleClass
{
public namespace sampleNamespace;
sampleNamespace function doSomething():void;
}
O ActionScript 3.0 permite incluir não apenas definições em um corpo da classe, mas também instruções. Instruções
que estão dentro de um corpo de classe, mas fora de uma definição do método, são executadas exatamente uma vez,
quando a definição da classe é encontrada primeiro e o objeto de classe associado é criado. O exemplo a seguir inclui
uma chamada para uma função externa, hello(), e uma instrução trace que produz uma mensagem de confirmação
quando a classe é definida:

function hello():String
{
trace(“hola”);
}
class SampleClass
{
hello();
trace(“class created”);
}
// output when class is created
hola
class created
Em contraste com versões anteriores do ActionScript, no ActionScript 3.0 é permitido definir uma propriedade
estática e uma propriedade de ocorrência com o mesmo nome no mesmo corpo da classe. Por exemplo, o código a
seguir declara uma variável estática denominada message e uma variável da ocorrência do mesmo nome:
class StaticTest
{
static var message:String = “static variable”;
var message:String = “instance variable”;
}
// In your script
var myST:StaticTest = new StaticTest();
trace(StaticTest.message); // output: static variable
trace(myST.message); // output: instance variable
Atributos de propriedade de classes
Em discussões do modelo de objeto do ActionScript, o termo property significa qualquer coisa que possa ser um
membro de uma classe, incluindo variáveis, constantes e métodos. Isso é diferente da maneira como o termo é usado
na Referência dos componentes e da linguagem do ActionScript 3.0, em que o termo é usado de maneira mais limitada
e inclui apenas membros de classes que são variáveis ou são definidos por um método getter ou setter. No ActionScript
3.0, há um conjunto de atributos que pode ser usado com qualquer propriedade de uma classe. A tabela a seguir lista
esse conjunto de atributos.

Sem título4

Atributos de espaço para nomes de controle de acesso
O ActionScript 3.0 fornece quatro atributos especiais que controlam o acesso às propriedades definidas dentro de uma
classe: public, private, protected e internal.
O atributo public torna a propriedade visível em qualquer lugar no script. Por exemplo, para disponibilizar um
método para o código fora de seu pacote, declare o método com o atributo public. Isso é verdadeiro para qualquer
propriedade, se ela for declarada usando as palavras-chave var, const ou function.

O atributo private torna a propriedade visível apenas para chamadores dentro da classe de definição da propriedade.
Esse comportamento é diferente daquele do atributo private no ActionScript 2.0, que permite que uma subclasse
acesse uma propriedade private em uma superclasse. Outra alteração significativa no comportamento que tem a ver
com acesso em tempo de execução. No ActionScript 2.0, a palavra-chave private proibia o acesso apenas em tempo
de compilação e era facilmente contornada em tempo de execução. No ActionScript 3.0, isso não é mais verdade.
Propriedades que estão marcadas como private não estão disponíveis em tempo de compilação e em tempo de
execução.
Por exemplo, o seguinte código cria uma classe simples denominada PrivateExample com uma variável private, e tenta
acessar a variável private de fora da classe. No ActionScript 2.0, o acesso em tempo de compilação era proibido, mas a
proibição era facilmente contornada usando o operador de acesso de propriedade ([]), que faz a pesquisa de
propriedades em tempo de execução em vez de em tempo de compilação.
class PrivateExample
{
private var privVar:String = “private variable”;
}
var myExample:PrivateExample = new PrivateExample();
trace(myExample.privVar);// compile-time error in strict mode
trace(myExample["privVar"]); // ActionScript 2.0 allows access, but in ActionScript 3.0, this
is a run-time error.
No ActionScript 3.0, uma tentativa de acessar uma propriedade private usando o operador ponto
(myExample.privVar) resultará em um erro em tempo de compilação se você estiver usando modo estrito. Caso
contrário, o erro será relatado em tempo de execução, exatamente como quando você usa o operador de acesso de
propriedade (myExample["privVar"]).
A tabela a seguir resume os resultados da tentativa de acessar uma propriedade private que pertence a uma classe selada
(não dinâmica):

Sem título5

Em classes declaradas com o atributo dynamic, as tentativas de acessar uma variável private não resultará em um erro
em tempo de execução. Em vez disso, a variável simplesmente não é visível, portanto, o Flash Player ou o Adobe® AIR™
retorna o valor undefined. No entanto, ocorrerá um erro em tempo de compilação, se você usar o operador ponto no
modo estrito. O exemplo a seguir é o mesmo do exemplo anterior, exceto que a classe PrivateExample é declarada
como uma classe dinâmica:
dynamic class PrivateExample
{
private var privVar:String = “private variable”;
}
var myExample:PrivateExample = new PrivateExample();
trace(myExample.privVar);// compile-time error in strict mode
trace(myExample["privVar"]); // output: undefined
As classes dinâmicas geralmente retornam o valor undefined em vez de gerar um erro quando o código externo a uma
classe tenta acessar uma propriedade private. A tabela a seguir mostra que um erro é gerado apenas quando o operador
ponto é usado para acessar uma propriedade private no modo estrito:

Sem título6

O atributo protected, que é novo para o ActionScript 3.0, torna uma propriedade visível a chamadores dentro de sua
própria classe ou em uma subclasse. Em outras palavras, uma propriedade protected está disponível dentro de sua
própria classe ou a classes que estão em qualquer lugar abaixo dela na hierarquia de heranças. Isso será verdadeiro se
a subclasse estiver no mesmo pacote ou em um pacote diferente.
Para quem está familiarizado com o ActionScript 2.0, essa funcionalidade é semelhante ao atributo private no
ActionScript 2.0. O atributo protected do ActionScript 3.0 também é semelhante ao atributo protected no Java, mas
difere já que a versão do Java também permite acesso a chamadores dentro do mesmo pacote. O atributo protected
é útil quando você tem uma variável ou método que as subclasses precisam, mas que você deseja ocultar do código que
está fora da cadeia de heranças.
O atributo internal, que é novo para o ActionScript 3.0, torna uma propriedade visível a chamadores dentro de seu
próprio pacote. Este é o atributo padrão do código dentro de um pacote e se aplica a qualquer propriedade que não
tenha nenhum dos seguintes atributos:
• public
• private
• protected
• um espaço para nomes definido pelo usuário
O atributo internal é semelhante ao controle de acesso padrão no Java, embora no Java não haja nenhum nome
explícito para este nível de acesso, e ele pode ser alcançado apenas por meio da omissão de qualquer outro modificador
de acesso. O atributo internal está disponível no ActionScript 3.0 para fornecer a opção de indicar explicitamente a
intenção tornar a propriedade visível apenas para chamadores dentro de seu próprio pacote.
atributo static
O atributo static, que pode ser usado com propriedades declaradas com as palavras-chave var, const ou function,
permite anexar uma propriedade à classe em vez de às ocorrências da classe. O código externo à classe deve chamar
propriedades estáticas usando o nome da classe em vez do nome de uma ocorrência.
As propriedades estáticas não são herdadas pelas subclasses, mas fazem parte da cadeia de escopos de uma subclasse.
Isso significa que dentro do corpo de uma subclasse, uma variável ou método estático pode ser usado sem fazer
referência à classe na qual ele foi definido.

Atributos de espaço para nomes definidos pelo usuário
Como alternativa aos atributos de controle de acesso predefinidos, você pode criar um espaço para nomes
personalizado para uso como um atributo. Apenas um atributo de espaço para nomes pode ser usado por definição, e
você não pode usar um atributo de espaço para nomes em combinação com qualquer um dos atributos de controle de
acesso (public, private, protected, internal).

Variáveis
As variáveis podem ser declaradas com as palavras-chave var ou const. Variáveis declaradas com a palavra-chave var
podem ter seus valores alterados várias vezes durante a execução de um script. Variáveis declaradas com a palavrachave
const são chamadas constants e valores podem ser atribuídos a elas apenas uma vez. Uma tentativa de atribuir
um novo valor a uma constante inicializada resulta em um erro.

Variáveis estáticas
As variáveis estáticas são declaradas usando uma combinação da palavra-chave static e da instrução var ou const.
As variáveis estáticas que são anexadas a uma classe em vez de a uma ocorrência de a uma classe são úteis para
armazenar e compartilhar informações que se aplicam a uma classe inteira de objetos. Por exemplo, uma variável
estática será apropriada se você desejar manter uma contagem do número de vezes que uma classe é instanciada ou se
desejar armazenar o número máximo de ocorrências da classe que são permitidas.
O exemplo a seguir cria uma variável totalCount para rastrear o número de instanciações de classes e uma constante
MAX_NUM para armazenar o número máximo de instanciações. As variáveis totalCount e MAX_NUM são estáticas
porque contêm valores que se aplicam à classe como um todo em vez de a uma ocorrência específica.
class StaticVars
{
public static var totalCount:int = 0;
public static const MAX_NUM:uint = 16;
}
O código que é externo à classe StaticVars e qualquer uma de suas subclasses pode fazer referência às propriedades
totalCount e MAX_NUM apenas por meio da própria classe. Por exemplo, o código a seguir funciona:
trace(StaticVars.totalCount); // output: 0
trace(StaticVars.MAX_NUM); // output: 16
Não é possível acessar variáveis estáticas por meio de uma ocorrência da classe, portanto, o código a seguir retorna
erros:
var myStaticVars:StaticVars = new StaticVars();
trace(myStaticVars.totalCount); // error
trace(myStaticVars.MAX_NUM); // error
Variáveis que são declaradas com as palavras-chave static e const devem ser inicializadas ao mesmo tempo em que
a constante é declarada, como faz a classe StaticVars para MAX_NUM. Você não pode atribuir um valor a MAX_NUM dentro
do construtor ou de um método da ocorrência. O código a seguir gerará um erro, porque não é uma maneira válida de
inicializar uma constante estática:
// !! Error to initialize static constant this way
class StaticVars2
{
public static const UNIQUESORT:uint;
function initializeStatic():void
{
UNIQUESORT = 16;
}
}

Variáveis de ocorrência
As variáveis de ocorrência incluem propriedades declaradas com as palavras-chave var e const, mas sem a palavrachave
static. As variáveis de ocorrência que são anexadas às ocorrências da classe em vez de a uma classe inteira são
úteis para armazenar valores específicos a uma ocorrência. Por exemplo, a classe Array tem uma propriedade de
ocorrência denominada length que armazena o número de elementos da matriz que é mantida por uma ocorrência
específica da classe Array.
Variáveis de ocorrência, se declaradas como var ou const, não podem ser substituídas em uma subclasse. No entanto,
você pode alcançar funcionalidade semelhante substituindo variáveis pelos métodos getter e setter.

Métodos
Métodos são funções que fazem parte de uma definição de classe. Depois que uma ocorrência da classe é criada, um
método é ligado a essa ocorrência. Ao contrário de uma função declarada fora de uma classe, um método não pode ser
usado à parte da ocorrência à qual ele está anexado.
Os métodos são definidos usando a palavra-chave function. Assim como em qualquer propriedade de classe, você
pode aplicar atributos de propriedade de classe a métodos, incluindo um espaço para nome privado, protegido,
público, interno, estático ou personalizado. Você pode usar uma instrução de função da seguinte maneira:
public function sampleFunction():String {}
Ou pode usar uma variável à qual atribuir uma expressão de função, da seguinte maneira:
public var sampleFunction:Function = function () {}
Na maior parte dos casos convém usar uma instrução function em vez de uma expressão function pelas seguintes
razões:
• As instruções function são mais concisas e mais fáceis de ler.
• As instruções function permitem usar as palavras-chave override e final.

• As instruções function criam uma ligação mais forte entre o identificador, isto é, o nome da função, e o código
dentro do corpo do método. Como o valor de uma variável pode ser alterado com uma instrução de atribuição, a
conexão entre uma variável e sua expressão de função pode ser desfeita a qualquer momento. Embora você possa
solucionar esse problema declarando a variável com const em vez de var, essa técnica não é considerada uma
prática recomendada, porque ela torna código difícil de ler e impede o uso das palavras-chave override e final.
Um caso em que você deve usar uma expressão function é ao optar por anexar uma função ao objeto de protótipo.

Métodos do construtor
Os métodos de construtor, às vezes chamados simplesmente de construtores, são funções que compartilham o mesmo
nome da classe na qual eles são definidos. Qualquer código incluído em um método de construtor é executado todas
as vezes que uma ocorrência da classe é criada com a palavra-chave new. Por exemplo, o código a seguir define uma
classe simples denominada Example que contém uma única propriedade denominada status. O valor inicial da
variável status é definido dentro da função de construtor.

class Example
{
public var status:String;
public function Example()
{
status = “initialized”;
}
}
var myExample:Example = new Example();
trace(myExample.status); // output: initialized
Os métodos de construtor podem ser apenas públicos, mas o uso do atributo public é opcional. Você não pode usar
nenhum dos outros especificadores de controle de acesso, inclusive private, protected ou internal, em um
construtor. Você também não pode usar um espaço para nomes definido pelo usuário com um método de construtor.
Um construtor pode fazer uma chamada explícita para o construtor de sua superclasse direta usando a instrução
super(). Se o construtor da superclasse não for chamado explicitamente, o compilador inserirá automaticamente
uma chamada antes da primeira instrução no corpo do construtor. Você também pode chamar métodos da superclasse
usando o prefixo super como uma referência à superclasse. Se você decidir usar super() e super no mesmo corpo
do construtor, verifique se super() é chamado primeiro. Caso contrário, a referência super não se comportará
conforme esperado. O construtor super() deve ser chamado também antes de qualquer instrução throw ou return.
O exemplo a seguir demonstra o que acontecerá se você tentar usar a referência super antes de chamar o construtor
super(). Uma nova classe, ExampleEx, estende a classe Example. O construtor ExampleEx tenta acessar a variável
status definida em sua superclasse, mas faz isso antes de chamar super(). A instrução trace() dentro do construtor
ExampleEx produz o valor null, porque a variável status não está disponível até que o construtor super() seja
executado.
class ExampleEx extends Example
{
public function ExampleEx()
{
trace(super.status);
super();
}
}
var mySample:ExampleEx = new ExampleEx(); // output: null
Embora seja válido usar a instrução return dentro de um construtor, não é permitido retornar um valor. Em outras
palavras, a instrução return não deve ter expressões ou valores associados. De forma correspondente, os métodos do
construtor não têm permissão para retornar valores, o que significa que nenhum tipo de retorno pode ser especificado.
Se você não definir um método de construtor em sua classe, o compilador criará automaticamente um construtor
vazio. Se a classe estender outra classe, o compilador incluirá uma chamada super() no construtor gerado.
Métodos estáticos
Os métodos estáticos, também chamados de métodos de classe, são métodos que são declarados com a palavra-chave
static. Os métodos estáticos que são anexados a uma classe e não em uma ocorrência de uma classe, são úteis para
encapsular a funcionalidade que afeta algo diferente do estado de uma ocorrência individual. Como os métodos
estáticos são anexados a uma classe como um todo, eles podem ser acessados apenas por meio de uma classe e não por
meio de uma ocorrência da classe.

Os métodos estáticos são úteis para encapsular funcionalidade que não está limitada a afetar o estado das ocorrências
da classe. Em outras palavras, um método deverá ser estático se fornecer funcionalidade que não afete diretamente o
valor de uma ocorrência de classe. Por exemplo, a classe Date tem um método estático denominado parse(), que
obtém uma string e converte-a em um número. O método é estático porque não afeta uma ocorrência individual da
classe. Em vez disso, o método parse() obtém uma string que representa um valor de data, analisa-a e retorna um
número em um formato compatível com a representação interna de um objeto Date. Esse método não é um método
da ocorrência, porque não faz sentido aplicar o método a uma ocorrência da classe Date.
Compare o método estático parse() com um dos métodos da ocorrência da classe Date, como getMonth(). O
método getMonth() é um método de ocorrência, porque ele opera diretamente no valor de uma ocorrência,
recuperando um componente específico, o mês, de uma ocorrência Date.
Como os métodos estáticos não estão ligados a ocorrências individuais, você não pode usar as palavras-chave this ou
super dentro do corpo de um método estático. As referências this e super têm significado apenas dentro do contexto
de um método de ocorrência.
Em comparação com algumas outras linguagens de programação com base em classe, os métodos estáticos no
ActionScript 3.0 não são herdados.

Métodos de ocorrência
Métodos de ocorrência são métodos declarados sem a palavra-chave static. Os métodos de ocorrência que são
anexados a ocorrências de uma classe e não à classe como um todo, são úteis para implementar a funcionalidade que
afeta ocorrências individuais de uma classe. Por exemplo, a classe Array contém um método de ocorrência
denominado sort() que opera diretamente em ocorrências de Array.
Dentro do corpo de um método de ocorrência, as variáveis de ocorrência e estáticas estão no escopo, o que significa
que as variáveis definidas na mesma classe podem ser referenciadas usando um identificador simples. Por exemplo, a
seguinte classe, CustomArray, estende a classe Array. A classe CustomArray define uma variável estática denominada
arrayCountTotal para rastrear o número total de ocorrências da classe, uma variável de ocorrência denominada
arrayNumber que rastreia a ordem na qual as ocorrências foram criadas e o método de ocorrência denominado
getPosition() que retorna os valores dessas variáveis.
public class CustomArray extends Array
{
public static var arrayCountTotal:int = 0;
public var arrayNumber:int;
public function CustomArray()
{
arrayNumber = ++arrayCountTotal;
}
public function getArrayPosition():String
{
return (“Array ” + arrayNumber + ” of ” + arrayCountTotal);
}
}

Embora o código externo à classe deva fazer referência à variável estática arrayCountTotal por meio do objeto de
classe, usando CustomArray.arrayCountTotal, o código que reside dentro do corpo do método getPosition()
pode fazer referência diretamente à variável estática arrayCountTotal. Isso é verdadeiro mesmo para variáveis
estáticas em superclasses. Apesar das propriedades estáticas não serem herdadas no ActionScript 3.0, as propriedades
estáticas em superclasses estão no escopo. Por exemplo, a classe Array tem algumas variáveis estáticas, uma das quais
é uma constante denominada DESCENDING. O código que reside em uma subclasse Array pode fazer referência à
constante estática DESCENDING usando um identificador simples:
public class CustomArray extends Array
{
public function testStatic():void
{
trace(DESCENDING); // output: 2
}
}
O valor da referência this dentro do corpo de um método da ocorrência é uma referência à ocorrência à qual o
método está anexado. O código a seguir demonstra que a referência this aponta para a ocorrência que contém o
método:
class ThisTest
{
function thisValue():ThisTest
{
return this;
}
}
var myTest:ThisTest = new ThisTest();
trace(myTest.thisValue() == myTest); // output: true
A herança de métodos de ocorrência pode ser controlada com as palavras-chave override e final. Você pode usar
o atributo override para redefinir um método herdado e o atributo final para impedir que as subclasses substituam
um método.

Métodos de acessor get e set
As funções de acessor get e set, também chamadas de getters e setters, permitem aderir aos princípios de programação
de ocultação de informações e encapsulamento enquanto fornece uma interface de programação fácil de usar para as
classes criadas. As funções get e set permitem manter as propriedades de classe privadas para a classe, mas permitem
que usuários da classe acessem essas propriedades como se fossem acessar uma variável de classe em vez de chamar
um método de classe.
A vantagem dessa abordagem é que ela permite evitar as funções de acessor tradicional com nomes inadequados, como
getPropertyName() e setPropertyName(). Outra vantagem de getters e setters é que você pode evitar ter duas
funções voltadas ao público para cada propriedade que permitam acesso de leitura e gravação.
O seguinte exemplo de classe, denominado GetSet, inclui funções do acessor get e set denominadas publicAccess()
que fornecem acesso à variável privada denominada privateProperty:

class GetSet
{
private var privateProperty:String;
public function get publicAccess():String
{
return privateProperty;
}
public function set publicAccess(setValue:String):void
{
privateProperty = setValue;
}
}
Se você tentar acessar a propriedade privateProperty diretamente, ocorrerá um erro, da seguinte maneira:
var myGetSet:GetSet = new GetSet();
trace(myGetSet.privateProperty); // error occurs
Em vez disso, um usuário da classe GetSet usa alguma coisa que parece ser uma propriedade denominada
publicAccess, mas que realmente é um par de funções de acessor get e set que operam na propriedade privada
denominada privateProperty. O exemplo a seguir instancia a classe GetSet e, em seguida, define o valor da
privateProperty usando o acessor público denominado publicAccess:
var myGetSet:GetSet = new GetSet();
trace(myGetSet.publicAccess); // output: null
myGetSet.publicAccess = “hello”;
trace(myGetSet.publicAccess); // output: hello
As funções getter e setter também permitem substituir propriedades que são herdadas de uma superclasse, algo que
não é possível ao usar variáveis de membros de classe normal. As variáveis de membros de classe que são declaradas
usando a palavra-chave var não podem ser substituídas em uma subclasse. No entanto as propriedades criadas usando
as funções getter e setter não têm essa restrição. É possível usar o atributo override nas funções getter e setter que são
herdadas de uma superclasse.
Métodos vinculados
Um método vinculado, às vezes chamado fechamento de método, é simplesmente um método extraído de sua
ocorrência. Os exemplos de métodos vinculados incluem métodos que são passados como argumentos para uma
função ou retornados de uma função como valores. Novo no ActionScript 3.0, um método vinculado é semelhante a
um fechamento de função já que ele retém seu ambiente léxico mesmo quando extraído de sua ocorrência. No entanto
a diferença principal entre um método vinculado e um fechamento de função é que a referência this de um método
vinculado permanece vinculada, ou ligada, à ocorrência que implementa o método. Em outras palavras, a referência
this em um método vinculado sempre aponta para o objeto original que implementou o método. Para fechamentos
de funções, a referência this é genérica, o que significa que ela aponta para qualquer objeto com o qual a função está
associada no momento em que é chamada.
É importante compreender os métodos vinculados ao usar a palavra-chave this. Lembre-se de que a palavra-chave
this fornece uma referência ao objeto pai de um método. A maioria dos programadores do ActionScript espera que
a palavra-chave this sempre faça referência ao objeto ou classe que contém a definição de um método. No entanto,
sem a vinculação do método, isso não é sempre verdadeiro. Em versões anteriores do ActionScript, por exemplo, a
referência this não se referia sempre à ocorrência que implementou o método. Quando os métodos são extraídos de

uma ocorrência no ActionScript 2.0, não somente a referência this não está vinculada à ocorrência original, mas
também os métodos as variáveis de membros da classe da ocorrência não estão disponíveis. Esse não é um problema
no ActionScript 3.0 porque os métodos vinculados são criados automaticamente quando você transmite um método
como um parâmetro. Os métodos vinculados garantem que a palavra-chave this sempre faça referência ao objeto ou
à classe na qual um método está definido.
O código a seguir define uma classe denominada ThisTest que contém um método denominado foo() que define o
método vinculado e um método denominado bar() que retorna o método vinculado. O código externo à classe cria
uma ocorrência da classe ThisTest, chama o método bar() e armazena o valor de retorno em uma variável
denominada myFunc.
class ThisTest
{
private var num:Number = 3;
function foo():void // bound method defined
{
trace(“foo’s this: ” + this);
trace(“num: ” + num);
}
function bar():Function
{
return foo; // bound method returned
}
}
var myTest:ThisTest = new ThisTest();
var myFunc:Function = myTest.bar();
trace(this); // output: [object global]
myFunc();
/* output:
foo’s this: [object ThisTest]
output: num: 3 */
As duas últimas linhas do código mostram que a referência this no método vinculado foo() ainda aponta para uma
ocorrência da classe ThisTest, mesmo que a referência this na linha imediatamente antes dela aponte para o objeto
global. Além disso, o método vinculado armazenado na variável myFunc ainda tem acesso às variáveis de membros da
classe ThisTest. Se esse mesmo código estiver em execução no ActionScript 2.0, as referências this corresponderão, e
a variável num será undefined.
Uma área em que a adição de métodos vinculados é mais perceptível é a de identificadores de eventos, porque o
método addEventListener() exige que você passe uma função ou método como um argumento.

Enumerações com classes
Enumerações são tipos de dados personalizados criados para encapsular um pequeno conjunto de valores. O
ActionScript 3.0 não oferece suporte a um recurso de enumeração específico, ao contrário do C++ com sua palavrachave
enum ou do Java com sua interface de Enumeração. No entanto, você pode criar enumerações usando classes e
constantes estáticas. Por exemplo, a classe PrintJob no ActionScript 3.0 usa uma enumeração denominada
PrintJobOrientation para armazenar o conjunto de valores que compõem “landscape” e “portrait”, conforme
mostrado no código a seguir:

public final class PrintJobOrientation
{
public static const LANDSCAPE:String = “landscape”;
public static const PORTRAIT:String = “portrait”;
}
Por convenção, uma classe de enumeração é declarada com o atributo final, porque não há nenhuma necessidade de
estender a classe. A classe inclui apenas membros estáticos, o que significa que você não cria ocorrências da classe. Em
vez disso, você acessa os valores de enumeração diretamente por meio do objeto de classe, conforme mostrado no
trecho de código a seguir:
var pj:PrintJob = new PrintJob();
if(pj.start())
{
if (pj.orientation == PrintJobOrientation.PORTRAIT)
{

}

}
Todas as classes de enumeração no ActionScript 3.0 contêm apenas variáveis do tipo String, int ou uint. A vantagem
de usar enumerações em vez de string literal ou valores numéricos é que os erros tipográficos são mais fáceis de
encontrar com enumerações. Se você digitar incorretamente o nome de uma enumeração, o compilador do
ActionScript gerará um erro. Se você usar valores literais, o compilador não reclamará se você digitar uma palavra
incorretamente ou usar um número incorreto. No exemplo anterior, o compilador gerará um erro se o nome da
constante de enumeração estiver incorreto, conforme mostrado no trecho a seguir:
if (pj.orientation == PrintJobOrientation.PORTRAI) // compiler error
No entanto o compilador não gerará um erro se você digitar de forma incorreta um valor literal da string, da seguinte
maneira:
if (pj.orientation == “portrai”) // no compiler error
A segunda técnica para criar enumerações também envolve a criação de uma classe separada com propriedades
estáticas para a enumeração. No entanto essa técnica difere já que cada uma das propriedades estáticas contém uma
ocorrência da classe em vez de uma string ou um valor inteiro. Por exemplo, o código a seguir cria uma classe de
enumeração para os dias da semana:
public final class Day
{
public static const MONDAY:Day = new Day();
public static const TUESDAY:Day = new Day();
public static const WEDNESDAY:Day = new Day();
public static const THURSDAY:Day = new Day();
public static const FRIDAY:Day = new Day();
public static const SATURDAY:Day = new Day();
public static const SUNDAY:Day = new Day();
}
Essa técnica não é usada pelo ActionScript 3.0, mas é usada por muitos desenvolvedores que preferem a verificação de
tipo aprimorada que a técnica fornece. Por exemplo, um método que retorna um valor de enumeração pode restringir
o valor de retorno para o tipo de dados de enumeração. O código a seguir mostra não apenas uma função que retorna
um dia da semana, mas também uma chamada de função que usa o tipo de enumeração como uma anotação de tipo:

function getDay():Day
{
var date:Date = new Date();
var retDay:Day;
switch (date.day)
{
case 0:
retDay = Day.MONDAY;
break;
case 1:
retDay = Day.TUESDAY;
break;
case 2:
retDay = Day.WEDNESDAY;
break;
case 3:
retDay = Day.THURSDAY;
break;
case 4:
retDay = Day.FRIDAY;
break;
case 5:
retDay = Day.SATURDAY;
break;
case 6:
retDay = Day.SUNDAY;
break;
}
return retDay;
}
var dayOfWeek:Day = getDay();
Você também pode aprimorar a classe Day para que ela associe um inteiro a cada dia da semana, e forneça um método
toString() que retorne uma representação da string do dia. Você pode desejar aprimorar a classe Day dessa maneira
como um exercício.
Classes de ativos incorporados
O ActionScript 3.0 usa classes especiais, chamadas classes de ativos incorporados, para representar ativos incorporados.
Um ativo incorporado é um ativo, como um som, imagem ou fonte, que é incluído em um arquivo SWF no momento
da compilação. Incorporar um ativo, em vez de carregá-lo dinamicamente, garante que ele estará disponível em tempo
de execução, mas ao custo do tamanho do arquivo SWF aumentado.
Uso de classes de ativos incorporados no Flash
Para incorporar um ativo, coloque primeiro o ativo em uma biblioteca do arquivo FLA. Em seguida, use a propriedade
de ligação do ativo para fornecer um nome para a classe de ativo incorporado. Se uma classe por esse nome não puder
ser encontrada no caminho de classe, ela será gerada automaticamente para você. Portanto você pode criar uma
ocorrência da classe de ativo incorporado e usar todas as propriedades e métodos definidos ou herdados por essa
classe. Por exemplo, o código a seguir pode ser usado para reproduzir um som incorporado que está vinculado a uma
classe de ativo incorporado denominada PianoMusic:
var piano:PianoMusic = new PianoMusic();
var sndChannel:SoundChannel = piano.play();

Interfaces
Uma interface é uma coleção de declarações de métodos que permite que objetos não relacionados se comuniquem.
Por exemplo, o ActionScript 3.0 define a interface IEventDispatcher que contém declarações de métodos que uma
classe pode usar para manipular objetos de eventos. A interface IEventDispatcher estabelece uma maneira padrão para
os objetos passarem objetos de eventos entre si. O código a seguir mostra a definição da interface IEventDispatcher:
public interface IEventDispatcher
{
function addEventListener(type:String, listener:Function,
useCapture:Boolean=false, priority:int=0,
useWeakReference:Boolean = false):void;
function removeEventListener(type:String, listener:Function,
useCapture:Boolean=false):void;
function dispatchEvent(event:Event):Boolean;
function hasEventListener(type:String):Boolean;
function willTrigger(type:String):Boolean;
}
As interfaces são baseadas na distinção entre uma interface do método e sua implementação. Uma interface do método
inclui todas as informações necessárias para chamá-lo, inclusive o nome do método, todos os seus parâmetros e seu
tipo de retorno. Uma implementação do método inclui não apenas as informações da interface, mas também as
instruções executáveis que executam o comportamento do método. Uma definição de interface contém apenas
interfaces do método, e qualquer classe que implemente a interface é responsável por definir as implementações do
método.
No ActionScript 3.0, a classe EventDispatcher implementa a interface IEventDispatcher definindo todos os métodos
da interface IEventDispatcher e adicionando corpos de métodos a cada um dos métodos. O exemplo a seguir é um
trecho da definição da classe EventDispatcher:
public class EventDispatcher implements IEventDispatcher
{
function dispatchEvent(event:Event):Boolean
{
/* implementation statements */
}

}
A interface IEventDispatcher serve como um protocolo que as ocorrências do EventDispatcher usam para processar
objetos de eventos e passá-los para outros objetos que também implementaram a interface IEventDispatcher.
Outra maneira de descrever uma interface é dizer que ela define um tipo de dados exatamente como faz uma classe.
Conseqüentemente, uma interface pode ser usada como uma anotação de tipo, exatamente como uma classe. Como
um tipo de dados, uma interface pode ser usada também com operadores, como os operadores is e as que exigem
um tipo de dados. No entanto, ao contrário de uma classe, uma interface não pode ser instanciada. Essa distinção levou
muitos programadores a considerar interfaces como tipos de dados abstratos e as classes como tipos de dados
concretos.

Definição de uma interface
A estrutura de uma definição de interface é semelhante à da definição de uma classe, exceto que uma interface pode
conter apenas métodos sem nenhum corpo de método. As interfaces não podem incluir variáveis ou constantes, mas
podem incluir getters e setters. Para definir uma interface, use a palavra-chave interface. Por exemplo, a seguinte
interface, IExternalizable, faz parte do pacote flash.utils no ActionScript 3.0. A interface IExternalizable define um
protocolo para serializar um objeto, o que significa converter um objeto em um formato adequado para
armazenamento em um dispositivo ou para transporte pela rede.
public interface IExternalizable
{
function writeExternal(output:IDataOutput):void;
function readExternal(input:IDataInput):void;
}
Observe que a interface IExternalizable é declarada com o modificador de controle de acesso public. As definições de
interface podem ser modificadas apenas pelos especificadores de controle de acesso public e internal. As
declarações de método dentro de uma definição de interface não podem ter nenhum especificador de controle de
acesso.
O ActionScript 3.0 segue uma convenção na qual os nomes de interface começam com um I maiúsculo, mas você pode
usar qualquer identificador válido como o nome de uma interface. As definições de interface são sempre colocadas no
nível superior de um pacote. As definições de interface não podem ser colocadas dentro de uma definição de classe ou
dentro da definição de outra interface.
As interfaces podem estender uma ou mais interfaces. Por exemplo, a seguinte interface, IExample, estende a interface
IExternalizable:
public interface IExample extends IExternalizable
{
function extra():void;
}
Qualquer classe que implemente a interface IExample deve incluir implementações não apenas para o método
extra(), mas também para os métodos writeExternal() e readExternal() herdados da interface IExternalizable.
Implementação de uma interface em uma classe
Uma classe é o único elemento de linguagem do ActionScript 3.0 que pode implementar uma interface. Use a palavrachave
implements em uma declaração de classe para implementar uma ou mais interfaces. O exemplo a seguir define
duas interfaces, IAlpha e IBeta, e uma classe, Alpha, que implementa as duas:
interface IAlpha
{
function foo(str:String):String;
}
interface IBeta
{
function bar():void;
}
class Alpha implements IAlpha, IBeta
{
public function foo(param:String):String {}
public function bar():void {}

Em uma classe que implementa uma interface, os métodos implementados devem fazer o seguinte:
• Usar o identificador de controle de acesso public.
• Usar o mesmo nome do método da interface.
• Ter o mesmo número de parâmetros, cada um com tipos de dados que correspondam aos tipos de dados do
parâmetro do método da interface.
• Usar o mesmo tipo de retorno.
public function foo(param:String):String {}
No entanto, você realmente tem alguma flexibilidade quanto a como nomear os parâmetros de métodos
implementados. Embora o número de parâmetros e o tipo de dados de cada parâmetro no método implementado
devam corresponder àquele do método da interface, os nomes de parâmetros não precisam corresponder. Por
exemplo, no exemplo anterior o parâmetro do método Alpha.foo() é denominado param:
Mas o parâmetro é denominado str no método da interface IAlpha.foo():
function foo(str:String):String;
Você tem também alguma flexibilidade com valores de parâmetro padrão. Uma definição de interface pode incluir
declarações de função com valores de parâmetro padrão. Um método que implementa um declaração de função desse
tipo deve ter um valor de parâmetro padrão que seja membro do mesmo tipo de dados que o valor especificado na
definição da interface, mas o valor real não precisa corresponder. Por exemplo, o código a seguir define uma interface
que contém um método com um valor de parâmetro padrão 3:
interface IGamma
{
function doSomething(param:int = 3):void;
}
A seguinte definição de classe implementa a interface Igamma, mas usa um valor do parâmetro padrão diferente:
class Gamma implements IGamma
{
public function doSomething(param:int = 4):void {}
}
O motivo dessa flexibilidade é que as regras para implementação de uma interface são projetadas especificamente para
garantir a compatibilidade do tipo de dados, e exigir nomes de parâmetros idênticos e valores de parâmetros padrão
não é necessário para atingir esse objetivo.
Herança
Herança é uma forma de reutilização de código que permite que programadores desenvolvam novas classes com base
em classes existentes. As classes existentes são sempre conhecidas como classes base ou superclasses, enquanto as novas
classes normalmente são chamadas de subclasses. A vantagem principal da herança é que ela permite reutilizar código
de uma classe base e ainda deixar o código existente inalterado. Além disso, a herança não requer nenhuma alteração
no modo como as outras classes interagem com a classe base. Em vez de modificar uma classe existente que pode ter
sido completamente testada ou já estar em uso, usando herança você pode tratar essa classe como um módulo
integrado que pode ser estendido com propriedades ou métodos adicionais. De forma correspondente, você usa a
palavra-chave extends para indicar que uma classe herda de outra classe.

A herança também permite que você se beneficie com o polimorfismo do código. Polimorfismo é a habilidade de usar
um único nome de método para um método que se comporta de maneira diferente ao ser aplicado a diferentes tipos
de dados. Um exemplo simples é uma classe base denominada Shape com duas subclasses denominadas Circle e
Square. A classe Shape define um método denominado area(), que retorna a área da forma. Se o polimorfismo estiver
implementado, você poderá chamar o método area() em objetos do tipo Circle e Square e fazer com que os cálculos
corretos sejam feitos para você. A herança ativa o polimorfismo permitindo que as subclasses sejam herdadas e
redefinidas, ou substituam, métodos da classe base. No exemplo a seguir, o método area() é redefinido pelas classes
Circle e Square:
class Shape
{
public function area():Number
{
return NaN;
}
}
class Circle extends Shape
{
private var radius:Number = 1;
override public function area():Number
{
return (Math.PI * (radius * radius));
}
}
class Square extends Shape
{
private var side:Number = 1;
override public function area():Number
{
return (side * side);
}
}
var cir:Circle = new Circle();
trace(cir.area()); // output: 3.141592653589793
var sq:Square = new Square();
trace(sq.area()); // output: 1
Como cada classe define um tipo de dados, o uso da herança cria um relacionamento especial entre a classe base e a
classe que a estende. Uma subclasse garantidamente possui todas as propriedades de sua classe base, o que significa
que uma ocorrência de uma subclasse pode ser sempre substituída por uma ocorrência da classe base. Por exemplo, se
um método definir um parâmetro do tipo Shape, é válido passar um argumento do tipo Circle, porque Circle estende
Shape, da seguinte maneira:
function draw(shapeToDraw:Shape) {}
var myCircle:Circle = new Circle();
draw(myCircle);

Propriedades da ocorrência e herança
Uma propriedade da ocorrência, se definida com as palavras-chave function, var ou const, será herdada por todas
as subclasses desde que a propriedade não seja declarada com o atributo private na classe base. Por exemplo, a classe
Event no ActionScript 3.0 tem várias subclasses que herdam propriedades comuns a todos os objetos de eventos.
Para alguns tipos de eventos, a classe Event contém todas as propriedades necessárias para definir o evento. Esses tipos
de eventos não exigem propriedades da ocorrência além daquelas definidas na classe Event. Exemplos desses eventos
são o evento complete, que ocorre quando os dados foram carregados com êxito, e o evento connect, que ocorre
quando uma conexão de rede foi estabelecida.
O exemplo a seguir é um fragmento da classe Event que mostra algumas das propriedades e métodos herdados por
subclasses. Como as propriedades são herdadas, uma ocorrência de qualquer subclasse pode acessar essas
propriedades.
public class Event
{
public function get type():String;
public function get bubbles():Boolean;

public function stopPropagation():void {}
public function stopImmediatePropagation():void {}
public function preventDefault():void {}
public function isDefaultPrevented():Boolean {}

}
Outros tipos de eventos exigem propriedades exclusivas não estão disponíveis na classe Event. Esses eventos são
definidos usando subclasses da classe Event para que novas propriedades possam ser adicionadas às propriedades
definidas na classe Event. Um exemplo dessa subclasse é a classe MouseEvent, que adiciona propriedades exclusivas a
eventos associados a movimento ou a cliques do mouse, como os eventos mouseMove e click. O exemplo a seguir é
um fragmento da classe MouseEvent que mostra a definição de propriedades que existem na subclasse, mas não na
classe base:
public class MouseEvent extends Event
{
public static const CLICK:String= “click”;
public static const MOUSE_MOVE:String = “mouseMove”;

public function get stageX():Number {}
public function get stageY():Number {}

}
Especificadores de controle de acesso e herança
Se uma propriedade for declarada com a palavra-chave public, ela será visível ao código em qualquer lugar. Isso
significa que a palavra-chave public, ao contrário das palavras-chave private, protected e internal, não coloca
nenhuma restrição sobre a herança da propriedade.
Se uma propriedade for declarada com a palavra-chave private, ela será visível apenas na classe que a define, o que
significa que não será herdada por nenhuma subclasse. Esse comportamento é diferente nas versões anteriores do
ActionScript, em que a palavra-chave private se comportava de maneira mais semelhante à palavra-chave
protected do ActionScript 3.0.

A palavra-chave protected indica que uma propriedade é visível não apenas dentro da classe que a define, mas
também a todas as subclasses. Ao contrário da palavra-chave protected na linguagem de programação Java, a
palavra-chave protected no ActionScript 3.0 não torna a propriedade visível para todas as outras classes no mesmo
pacote. No ActionScript 3.0, apenas as subclasses podem acessar uma propriedade declarada com a palavra-chave
protected. Além disso, uma propriedade protegida será visível para uma subclasse, se a subclasse estiver no mesmo
pacote da classe base ou em um pacote diferente.
Para limitar a visibilidade de uma propriedade para o pacote no qual ela está definida, use a palavra-chave internal
ou não use nenhum especificador de controle de acesso. O especificador de controle de acesso internal é o
especificador padrão aplicado quando um não está especificado. Uma propriedade marcada como internal será
herdada apenas por uma subclasse que reside no mesmo pacote.
Você pode usar o exemplo a seguir para ver como cada um dos especificadores de controle de acesso afeta a herança
entre limites de pacotes. O código a seguir define uma classe de aplicativo principal denominada AccessControl e duas
outras classes denominadas Base e Extender. A classe Base está em um pacote denominado foo e a classe Extender, que
é uma subclasse da classe Base, está em um pacote denominado bar. A classe AccessControl importa apenas a classe
Extender e cria uma ocorrência de Extender que tenta acessar uma variável denominada str definida na classe Base.
A variável str é declarada como public para que o código seja compilado e executado, conforme mostrado no
seguinte trecho:
// Base.as in a folder named foo
package foo
{
public class Base
{
public var str:String = “hello”; // change public on this line
}
}
// Extender.as in a folder named bar
package bar
{
import foo.Base;
public class Extender extends Base
{
public function getString():String {
return str;
}
}
}
// main application class in file named AccessControl.as
package
{
import flash.display.MovieClip;
import bar.Extender;
public class AccessControl extends MovieClip
{
public function AccessControl()
{
var myExt:Extender = new Extender();
trace(myExt.str);// error if str is not public
trace(myExt.getString()); // error if str is private or internal
}
}
}

Para ver como os outros especificadores de controle de acesso afetam a compilação e a execução do exemplo anterior,
altere o especificador de controle de acesso da variável str para private, protected ou internal após excluir ou
comentar a linha seguinte da classe AccessControl:
trace(myExt.str);// error if str is not public
Substituição de variáveis não permitidas
As propriedades declaradas com as palavras-chave var ou const são herdadas, mas não podem ser substituídas.
Substituir uma propriedade significa redefini-la em uma subclasse. O único tipo de propriedade que pode ser
substituído são os métodos, isto é, propriedades declaradas com a palavra-chave function. Embora não seja possível
substituir uma variável de ocorrência, você pode alcançar funcionalidade semelhante criando os métodos getter e
setter para a variável de ocorrência e substituindo os métodos.

Substituição de métodos
Substituir um método significa redefinir o comportamento de um método herdado. Métodos estáticos não são
herdados e não podem ser substituídos. No entanto métodos de ocorrência são herdados por subclasses e podem ser
substituídos desde que os dois seguintes critérios sejam atendidos:
• O método da ocorrência não é declarado com a palavra-chave final na classe base. Quando usada com um método
da ocorrência, a palavra-chave final indica a intenção do programador de impedir que as subclasses substituam
o método.
• O método da ocorrência não é declarado com o especificador de controle de acesso private na classe base. Se um
método estiver marcado como private na classe base, não haverá necessidade de usar a palavra-chave override
ao definir um método nomeado de maneira idêntica na subclasse, porque o método da classe base não será visível
para a subclasse.
Para substituir um método da ocorrência que atenda a esses critérios, a definição do método na subclasse deve usar
a palavra-chave override e deve corresponder à versão da superclasse do método das seguintes maneiras:
• O método de substituição deve ter o mesmo nível de controle de acesso do método da classe base. Métodos
marcados como internos têm o mesmo nível de controle de acesso que os métodos que não têm nenhum
especificador de controle de acesso.
• O método de substituição deve ter o mesmo número de parâmetros que o método da classe base.
• Os parâmetros do método de substituição devem ter as mesmas anotações de tipo de dados que os parâmetros do
método da classe base.
• O método de substituição deve ter o mesmo tipo de retorno que o método da classe base.
No entanto os nomes dos parâmetros no método de substituição não precisam corresponder aos nomes dos
parâmetros na classe base, desde que o número de parâmetros e o tipo de dados de cada parâmetro correspondam.
A instrução super
Ao substituir um método, os programadores sempre querem aumentar o comportamento do método da superclasse
que estão substituindo, em vez de substituir completamente o comportamento. Isso requer um mecanismo que
permita que um método em uma subclasse chame a versão da superclasse de si próprio. A instrução super fornece
esse mecanismo, já que ela contém uma referência à superclasse imediata. O exemplo a seguir define uma classe
denominada Base que contém um método denominado thanks() e uma subclasse da classe Base denominada
Extender que substitui o método thanks(). O método Extender.thanks() usa a instrução super para chamar
Base.thanks().

package {
import flash.display.MovieClip;
public class SuperExample extends MovieClip
{
public function SuperExample()
{
var myExt:Extender = new Extender()
trace(myExt.thanks()); // output: Mahalo nui loa
}
}
}
class Base {
public function thanks():String
{
return “Mahalo”;
}
}
class Extender extends Base
{
override public function thanks():String
{
return super.thanks() + ” nui loa”;
}
}
Substituição de getters e setters
Embora não seja possível substituir variáveis definidas em uma superclasse, você pode substituir getters e setters. Por
exemplo, o código a seguir substitui um getter denominado currentLabel que é definido na classe MovieClip no
ActionScript 3.0:
package
{
import flash.display.MovieClip;
public class OverrideExample extends MovieClip
{
public function OverrideExample()
{
trace(currentLabel)
}
override public function get currentLabel():String
{
var str:String = “Override: “;
str += super.currentLabel;
return str;
}
}
}
A saída da instrução trace() no construtor da classe OverrideExample é Override: null, que mostra que o exemplo
pôde substituir a propriedade currentLabel herdada.

Propriedades estáticas não herdadas
Propriedades estáticas não são herdadas por subclasses. Isso significa que as propriedades estáticas não podem ser
acessadas por meio de uma ocorrência de uma subclasse. Uma propriedade estática pode ser acessada apenas por meio
do objeto da classe no qual ela é definida. Por exemplo, o código a seguir define uma classe base denominada Base e
uma subclasse denominada Extender que estende a Base. Uma variável estática denominada test é definida na classe
Base. O código conforme escrito no fragmento a seguir, não é compilado no modo estrito e gera um erro em tempo de
execução no modo padrão.
package {
import flash.display.MovieClip;
public class StaticExample extends MovieClip
{
public function StaticExample()
{
var myExt:Extender = new Extender();
trace(myExt.test);// error
}
}
}
class Base {
public static var test:String = “static”;
}
class Extender extends Base { }
A única maneira de acessar a variável estática test é por meio do objeto da classe, conforme mostrado no código a
seguir:
Base.test;
No entanto é permitido definir uma propriedade da ocorrência usando o mesmo nome de uma propriedade estática.
Essa propriedade da ocorrência pode ser definida na mesma classe que a propriedade estática ou em uma subclasse.
Por exemplo, a classe Base no exemplo anterior podia ter uma propriedade da ocorrência denominada test. O código
a seguir é compilado e executado porque a propriedade da ocorrência é herdada pela classe Extender. O código
também será compilado e executado, se a definição da variável da ocorrência de teste for movida, mas não copiada,
para a classe Extender.

package
{
import flash.display.MovieClip;
public class StaticExample extends MovieClip
{
public function StaticExample()
{
var myExt:Extender = new Extender();
trace(myExt.test);// output: instance
}
}
}
class Base
{
public static var test:String = “static”;
public var test:String = “instance”;
}
class Extender extends Base {}
Propriedades estáticas e a cadeia de escopos
Embora as propriedades estáticas não sejam herdadas, elas estão dentro da cadeia do escopo da classe que as define e
em qualquer subclasse dessa classe. Como tal, diz-se que as propriedades estáticas estão in scope da classe na qual elas
são definidas e em qualquer subclasse. Isso significa que uma propriedade estática pode ser acessada diretamente
dentro do corpo da classe que a define e em qualquer subclasse dessa classe.
O exemplo a seguir modifica as classes definidas no exemplo anterior para mostrar que a variável estática test
definida na classe Base está no escopo da classe Extender. Em outras palavras, a classe Extender pode acessar a variável
estática test sem prefixar a variável com o nome da classe que define test.
package
{
import flash.display.MovieClip;
public class StaticExample extends MovieClip
{
public function StaticExample()
{
var myExt:Extender = new Extender();
}
}
}
class Base {
public static var test:String = “static”;
}
class Extender extends Base
{
public function Extender()
{
trace(test); // output: static
}
}

Se for definida uma propriedade de ocorrência que usa o mesmo nome que uma propriedade estática na mesma classe
ou em uma superclasse, a propriedade de ocorrência terá precedência mais alta na cadeia do escopo. Diz-se que a
propriedade da ocorrência sombreia a propriedade estática, o que significa que o valor da propriedade da ocorrência
é usado no lugar do valor da propriedade estática. Por exemplo, o código a seguir mostra que se a classe Extender
definir uma variável da ocorrência denominada test, a instrução trace() usará o valor da variável da ocorrência em
vez do valor da variável estática:
package
{
import flash.display.MovieClip;
public class StaticExample extends MovieClip
{
public function StaticExample()
{
var myExt:Extender = new Extender();
}
}
}
class Base
{
public static var test:String = “static”;
}
class Extender extends Base
{
public var test:String = “instance”;
public function Extender()
{
trace(test); // output: instance
}
}
Tópicos avançados
Esta seção é iniciada com um breve histórico do ActionScript e do OOP e continua com uma discussão do modelo de
objeto do ActionScript 3.0 e como ele permite que o novo AVM2 (ActionScript Virtual Machine) execute de maneira
significativamente mais rápida do que em versões anteriores do Flash Player que contêm o AVM1 (ActionScript
Virtual Machine) antigo.
Histórico do suporte da OOP ao ActionScript
Como o ActionScript 3.0 foi criado sobre versões anteriores do ActionScript, é útil compreender como o modelo de
objeto do ActionScript evoluiu. O ActionScript começou como um mecanismo de script simples para versões
anteriores da ferramenta de autoria do Flash. Subseqüentemente, os programadores começaram a criar aplicativos
cada vez mais complexos com o ActionScript. Em resposta às necessidades desses programadores, cada versão
subseqüente adicionou recursos de linguagem que facilitam a criação de aplicativos complexos.

ActionScript 1.0
O ActionScript 1.0 faz referência à versão da linguagem usada no Flash Player 6 e anterior. Mesmo na primeira fase de
desenvolvimento, o modelo de objeto do ActionScript era baseado no conceito do objeto como um tipo de dados
fundamental. Um objeto do ActionScript é um tipo de dados composto por um grupo de propriedades. Ao discutir o
modelo de objeto, o termo propriedades inclui tudo o que está conectado a um objeto, como variáveis, funções ou
métodos.
Embora essa primeira geração do ActionScript não ofereça suporte à definição de classes com uma palavra-chave
class, é possível definir uma classe usando um tipo especial de objeto chamado objeto de protótipo. Em vez de usar
uma palavra-chave class para criar uma definição de classe abstrata que você instancia em objetos concretos, como
o faz em linguagens baseadas em classe, como Java e C++, as linguagens baseadas em protótipo como o ActionScript
1.0 usam um objeto existente como um modelo (ou protótipo) para outros objetos. Enquanto objetos em uma
linguagem baseada em classe podem apontar para uma classe que serve como seu modelo, objetos em uma linguagem
baseada em protótipo apontam para outro objeto, seu protótipo, que serve como seu modelo.
Para criar uma classe no ActionScript 1.0, defina uma função de construtor para essa classe. No ActionScript, as
funções são objetos reais, não apenas definições abstratas. A função de construtor que você cria serve como o objeto
de protótipo para ocorrências dessa classe. O código a seguir cria uma classe denominada Shape e define uma
propriedade denominada visible que, por padrão, é definida como true:
// base class
function Shape() {}
// Create a property named visible.
Shape.prototype.visible = true;
Essa função de construtor define uma classe Shape que você pode instanciar com o operador new, da seguinte maneira:
myShape = new Shape();
Do mesmo modo como o objeto de função de construtor Shape() serve como protótipo para ocorrências da classe
Shape, ele também pode servir como o protótipo para subclasses de Shape, isto é, outras classes que estendem a classe
Shape.
A criação de uma classe que é uma subclasse da classe Shape é um processo de duas etapas. Primeiro, crie a classe
definindo uma função de construtor para a classe, da seguinte maneira:
// child class
function Circle(id, radius)
{
this.id = id;
this.radius = radius;
}
Segundo, use o operador new para declarar que a classe Shape é o protótipo para a classe Circle. Por padrão, qualquer
classe criada usa a classe Object como seu protótipo, o que significa que Circle.prototype atualmente contém um
objeto genérico (uma ocorrência da classe Object). Para especificar que o protótipo de Circle é Shape em vez de Object,
use o código a seguir para alterar o valor de Circle.prototype para que ele contenha um objeto Shape em vez de um
objeto genérico:
// Make Circle a subclass of Shape.
Circle.prototype = new Shape();

As classes Shape e Circle estão agora vinculadas em conjunto em um relacionamento de herança que é conhecido como
a cadeia de protótipos. O diagrama ilustra os relacionamentos em uma cadeia de protótipos:

Sem título7

A classe base no final de cada cadeia de protótipos é a classe Object. A classe Object contém uma propriedade estática
denominada Object.prototype que aponta para o objeto de protótipo base de todos os objetos criados no
ActionScript 1.0. O próximo objeto em nossa cadeia de protótipos de exemplo é o objeto Shape. Isso ocorre porque a
propriedade Shape.prototype nunca foi definida explicitamente, portanto ela ainda mantém um objeto genérico
(uma ocorrência da classe Object). O link final nessa cadeia é a classe Circle que está vinculada a seu protótipo, a classe
Shape (a propriedade Circle.prototype mantém um objeto Shape).
Se criarmos uma ocorrência da classe Circle, como no seguinte exemplo, a ocorrência herdará a cadeia de protótipos
da classe Circle:
// Create an instance of the Circle class.
myCircle = new Circle();
Lembre-se de que criamos uma propriedade denominada visible como um membro da classe Shape. Em nosso
exemplo, a propriedade visible não existe como parte do objeto myCircle, apenas como membro do objeto Shape,
apesar da linha seguinte do código produzir true:
trace(myCircle.visible); // output: true
O Flash Player pode verificar se o objeto myCircle herda a propriedade visible percorrendo a cadeia de protótipos.
Ao executar este código, o Flash Player primeiro pesquisa a propriedades do objeto myCircle por uma propriedade
denominada visible, mas não encontra essa propriedade. Em seguida, o Flash Player verifica o objeto
Circle.prototype, mas ainda não encontra uma propriedade denominada visible. Continuando na cadeia de
protótipos, o Flash Player finalmente encontra a propriedade visible definida no objeto Shape.prototype e fornece
o valor daquela propriedade.
Pelo bem da simplicidade, esta seção omite muitos dos detalhes e complexidades da cadeia de protótipos e tem o
objetivo de fornecer informações suficientes para ajudar a compreender o modelo de objeto do ActionScript 3.0.
ActionScript 2.0
O ActionScript 2.0 introduziu novas palavras-chave, como class, extends, publice private, que permitiram
definir classes de uma maneira que seja familiar a qualquer pessoa que trabalhe com linguagens baseadas em classes
como Java e C++. É importante compreender que o mecanismo da herança subjacente não foi alterado entre o
ActionScript 1.0 e o ActionScript 2.0. O ActionScript 2.0 simplesmente adicionou uma nova sintaxe para definir
classes. A cadeia de protótipos funciona da mesma maneira nas duas versões da linguagem.
A nova sintaxe introduzida pelo ActionScript 2.0, mostrada no trecho a seguir, permite definir classes de uma maneira
que é considerada intuitiva por muitos programadores:

// base class
class Shape
{
var visible:Boolean = true;
}
Observe que o ActionScript 2.0 também introduziu anotações de tipo para uso com verificação de tipos em tempo de
compilação. Isso permite declarar que a propriedade visible no exemplo anterior deve conter apenas um valor
booleano. A nova palavra-chave extends também simplifica o processo de criação de uma subclasse. No exemplo a
seguir, o processo em duas etapas necessário no ActionScript 1.0 é executado em uma etapa com a palavra-chave
extends:
// child class
class Circle extends Shape
{
var id:Number;
var radius:Number;
function Circle(id, radius)
{
this.id = id;
this.radius = radius;
}
}
O construtor está agora declarado como parte da definição da classe e as propriedades de classes id e radius também
devem ser declaradas explicitamente.
O ActionScript 2.0 também adicionou suporte para a definição de interfaces, o que permite refinar ainda mais os
programas orientados a objetos com protocolos definidos formalmente para comunicação entre objetos.
Objeto de classe do ActionScript 3.0
Um paradigma comum da programação orientada a objetos, mais freqüentemente associado a Java e C++, usa classes
para definir tipos de objetos. Linguagens de programação que adotam esse paradigma também tendem a usar classes
para construir ocorrências do tipo de dados que a classe define. O ActionScript usa classes para duas dessas finalidades,
mas suas raízes como uma linguagem com base em protótipo adicionam uma característica interessante. O
ActionScript cria para cada definição de classe um objeto de classe especial que permite o compartilhamento do
comportamento e do estado. No entanto, para muitos programadores do ActionScript, esta distinção não pode ter
nenhuma implicação de codificação prática. O ActionScript 3.0 é projetado de forma que você possa criar aplicativos
do ActionScript orientados a objetos sofisticados sem usar, ou mesmo compreender, esses objetos de classes especiais.
Para programadores avançados que desejam tirar proveito de objetos de classes, esta seção discute os problemas em
profundidade.

O diagrama a seguir mostra a estrutura de um objeto de classe que representa uma classe simples denominada A que
é definida com a instrução class A {}:

Sem título8

Cada retângulo no diagrama representa um objeto. Cada objeto no diagrama tem um caractere subscrito A para

representar que ele pertence à classe A. O objeto de classe (CA) contém referências a vários outros objetos importantes.
Um objeto com características da ocorrência (TA) armazena as propriedades da ocorrência que são definidas dentro
de uma definição de classe. Um objeto de características da classe (TCA) representa o tipo interno da classe e armazena
as propriedades estáticas definidas pela classe (o caractere subscrito C representa a “classe”). O objeto de protótipo
(PA) sempre faz referência ao objeto da classe ao qual ele era originalmente anexado por meio da propriedade
constructor.
Objeto de características
O objeto de características, novo no ActionScript 3.0, foi implementado tendo em mente o desempenho. Em versões
anteriores do ActionScript, a pesquisa de nome era um processo demorado pois o Flash Player percorria a cadeia de
protótipos. No ActionScript 3.0, a pesquisa de nome é muito mais eficiente e menos demorada, porque as propriedades
herdadas são copiadas das superclasses no objeto de características de subclasses.
O objeto de características não pode ser acessado diretamente pelo código do programador, mas sua presença pode ser
sentida pelos aprimoramentos no desempenho e no uso de memória. O objeto de características fornece ao AVM2
informações detalhadas sobre o layout e o conteúdo de uma classe. Com esse conhecimento, o AVM2 pode reduzir
significativamente o tempo de execução, porque pode gerar freqüentemente instruções de máquina diretas para
acessar propriedades ou chamar métodos diretamente sem uma pesquisa de nome demorada.
Graças ao objeto de características, uma superfície de memória do objeto pode ser significativamente menor do que a
de um objeto semelhante em versões anteriores do ActionScript. Por exemplo, se uma classe estiver selada (isto é, a
classe não está declarada dinâmica), uma ocorrência da classe não precisará de uma tabela hash para propriedades
adicionadas dinamicamente, e poderá manter um pouco mais do que um ponteiro para os objetos de características e
alguns slots para as propriedades fixas definidas na classe. Como resultado, um objeto que exigia 100 bytes de memória
no ActionScript 2.0 pode exigir apenas 20 bytes de memória no ActionScript 3.0.
Nota: O objeto de características é um detalhe da implementação interna, e não há nenhuma garantia de que ele não
seja alterado ou mesmo que desapareça em versões futuras do ActionScript.

Objeto de protótipo
Cada objeto de classe do ActionScript tem uma propriedade denominada prototype, que é uma referência ao objeto
de protótipo da classe. O objeto de protótipo é um herança das raízes do ActionScript como linguagem com base em
protótipo.

A propriedade prototype é somente leitura, o que significa que não pode ser modificada para apontar para objetos
diferentes. Ela é diferente da propriedade prototype da classe em versões anteriores do ActionScript, em que o
protótipo podia ser reatribuído para que apontasse para uma classe diferente. Embora a propriedade prototype seja
somente leitura, o objeto de protótipo ao qual ela faz referência não é. Em outras palavras, novas propriedades podem
ser adicionadas ao objeto de protótipo. Propriedades adicionadas ao objeto de protótipo são compartilhadas entre
todas as ocorrências da classe.
A cadeia de protótipos, que era o único mecanismo de herança em versões anteriores do ActionScript, serve apenas
uma função secundária no ActionScript 3.0. O mecanismo de herança principal, herança de propriedade fixa, é
manipulado internamente pelo objeto de características. Uma propriedade fixa é uma variável ou método que é
definida como parte de uma definição de classe. A herança de propriedade fixa também é de chamada herança de
classe, porque ela é o mecanismo de herança associado a palavras-chave, como class, extends e override.
A cadeia de protótipos fornece um mecanismo de herança alternativa que é mais dinâmico do que a herança de
propriedade fixa. Você pode adicionar propriedades a um objeto de protótipo de classe não apenas como parte da
definição da classe, mas também em tempo de execução por meio da propriedade prototype do objeto de classe. No
entanto, observe que se você definir o compilador como modo estrito, talvez não seja possível acessar propriedades
adicionadas a um objeto de protótipo, a não ser que você declare uma classe com a palavra-chave dynamic.
Um bom exemplo de uma classe com várias propriedades anexadas ao objeto de protótipo é a classe Object. Os
métodos toString() e valueOf() da classe Object são realmente funções atribuídas às propriedades do objeto de
protótipo da classe Object. A seguir está um exemplo de como pode ser a aparência da declaração desses métodos, em
teoria, (a implementação real é um pouco diferente, por causa dos detalhes da implementação):
public dynamic class Object
{
prototype.toString = function()
{
// statements
};
prototype.valueOf = function()
{
// statements
};
}
Conforme mencionado anteriormente, é possível anexar uma propriedade a um objeto de protótipo de classe fora da
definição de classe. Por exemplo, o método toString() também pode ser definido fora da definição da classe Object,
da seguinte maneira:
Object.prototype.toString = function()
{
// statements
};

No entanto, ao contrário da herança de propriedade fixa, a herança de protótipo não exigirá a palavra-chave override,
se você desejar redefinir um método em uma subclasse. Por exemplo: se você desejar redefinir o método valueOf()
em uma subclasse da classe Object, terá três opções. Primeiro, você pode definir um método valueOf() no objeto de
protótipo de subclasse dentro da definição de classe. O código a seguir cria uma subclasse de Object denominada Foo
e redefine o método valueOf() no objeto de protótipo de Foo como parte da definição de classe. Como cada classe é
herdada de Object, não é necessário usar a palavra-chave extends.
dynamic class Foo
{
prototype.valueOf = function()
{
return “Instance of Foo”;
};
}
Segundo, você pode definir um método valueOf() no objeto de protótipo de Foo fora da definição de classe,
conforme mostrado no código a seguir:
Foo.prototype.valueOf = function()
{
return “Instance of Foo”;
};
Terceiro, você pode definir uma propriedade fixa denominada valueOf() como parte da classe Foo. Essa técnica é
diferente das outras já que ela mescla herança de propriedade fixa com herança de protótipo. Qualquer subclasse de
Foo que precise redefinir valueOf() deve usar a palavra-chave override. O código a seguir mostra valueOf()
definido como uma propriedade fixa em Foo:
class Foo
{
function valueOf():String
{
return “Instance of Foo”;
}
}
Espaço para nomes AS3
A existência de dois mecanismos de herança separados, herança de propriedade fixa e herança de protótipo, cria uma
desafio de compatibilidade interessante em relação às propriedades e métodos das classes principais. A
compatibilidade com a especificação de linguagem do ECMAScript na qual o ActionScript é baseado exige o uso de
herança de protótipo, o que significa que as propriedades e métodos de uma classe principal são definidos no objeto
de protótipo dessa classe. Por outro lado, a compatibilidade com o ActionScript 3.0 exige o uso de herança de
propriedade fixa, o que significa que as propriedades e métodos de uma classe principal são definidos na definição da
classe usando as palavras-chave const, var e function. Além disso, o uso de propriedades fixas, em vez das versões
do protótipo pode levar a aumentos significativos no desempenho em tempo de execução.
O ActionScript 3.0 resolve esse problema usando herança de protótipo e herança de propriedade fixa para as classes
principais. Cada classe principal contém dois conjuntos de propriedades e métodos. Um conjunto é definido no objeto
de protótipo para compatibilidade com a especificação do ECMAScript, e o outro conjunto é definido com
propriedades fixas e o espaço para nomes AS3 para compatibilidade com o ActionScript 3.0.

O espaço para nomes AS3 fornece um mecanismo conveniente para escolher entre os dois conjuntos de propriedades
e métodos. Se você não usar o espaço para nomes AS3, uma ocorrência de uma classe principal herdará as propriedades
e métodos definidos no objeto de protótipo da classe principal. Se você decidir usar o espaço para nomes AS3, uma
ocorrência de uma classe principal herdará as versões do AS3, porque as propriedades fixas são sempre preferidas
sobre as propriedades de protótipo. Em outras palavras, sempre que uma propriedade fixa estiver disponível, ela será
sempre usada no lugar de uma propriedade de protótipo nomeada de forma idêntica.
Você pode usar seletivamente a versão do espaço para nomes AS3 de uma propriedade ou método qualificando-a com
o espaço para nomes AS3. Por exemplo, o código a seguir usa a versão do AS3 do método Array.pop():
var nums:Array = new Array(1, 2, 3);
nums.AS3::pop();
trace(nums); // output: 1,2
Como alternativa, você pode usar a diretiva use namespace para abrir o espaço para nomes AS3 para todas as
definições dentro de um bloco de código. Por exemplo, o código a seguir usa a diretiva use namespace para abrir o
espaço para nomes AS3 para os métodos pop() e push():
use namespace AS3;
var nums:Array = new Array(1, 2, 3);
nums.pop();
nums.push(5);
trace(nums) // output: 1,2,5
O ActionScript 3.0 também fornece opções de compilador para cada conjunto de propriedades para que você possa
aplicar o espaço para nomes AS3 ao programa inteiro. A opção de compilador -as3 representa o espaço para nomes
AS3, e a opção de compilador -es representa a opção de herança de protótipo (es representa o ECMAScript). Para
abrir o espaço para nomes AS3 para o programa inteiro, defina a opção de compilador -as3 como true e a opção de
compilador -es como false. Para usar as versões de protótipo, defina as opções do compilador como os valores
opostos. As configurações do compilador padrão do Adobe Flex Builder 3 e do Adobe Flash CS4 Professional são -as3
= true e -es = false.
Se você planejar estender qualquer uma das classes principais e substituir qualquer método, deverá compreender como
o espaço para nomes AS3 pode afetar o modo como você deve declarar um método substituído. Se você estiver usando
o espaço para nomes AS3, qualquer substituição de método de um método da classe principal também deve usar o
espaço para nomes AS3 juntamente com o atributo override. Se não estiver usando o espaço para nomes AS3 e
desejar redefinir um método da classe principal em uma subclasse, você não deverá usar o espaço para nomes AS3 ou
a palavra-chave override.
Exemplo: GeometricShapes
O aplicativo de amostra GeometricShapes mostra como vários conceitos e recursos orientados a objetos podem ser
aplicados usando o ActionScript 3.0, inclusive:
• Definição de classes
• Extensão de classes
• Polimorfismo e a palavra-chave override
• Definição, extensão e implementação de interfaces
Ele também inclui um “método de fábrica” que cria ocorrências de classes, mostrando como declarar um valor de
retorno como uma ocorrência de uma interface, e usar esse objeto retornado de uma maneira genérica.

Para obter os arquivos do aplicativo desta amostra, consulte
http://www.adobe.com/go/learn_programmingAS3samples_flash_br. Os arquivos do aplicativo GeometricShapes podem
ser encontrados na pasta Amostras/GeometricShapes. O aplicativo consiste nos seguintes arquivos:

Sem título9

Definição das classes GeometricShapes
O aplicativo GeometricShapes permite que o usuário especifique um tipo de forma geométrica e um tamanho. Em
seguida, ele responde com uma descrição da forma, sua área e a distância em torno de seu perímetro.
A interface de usuário do aplicativo é trivial, incluindo alguns controles para seleção do tipo de forma, configuração
do tamanho e exibição da descrição. A parte mais interessante desse aplicativo está sob a superfície, na estrutura das
classes e das próprias interfaces.
Esse aplicativo trata de formas geométricas, mas não as exibe graficamente. Ele fornece uma pequena biblioteca de
classes e interfaces que serão reutilizadas no exemplo de um exemplo capítulo posterior. O exemplo SpriteArranger exibe as formas graficamente e permite que o usuário asmanipule, com base na estrutura da classe fornecida aqui no aplicativo GeometricShapes.
As classes e interfaces que definem as formas geométricas neste exemplo são mostradas no diagrama a seguir que usa
a notação UML (Linguagem de modelação unificada):

Sem título10

Definição do comportamento comum com interfaces
Este aplicativo GeometricShapes trata de três tipos de formas: círculos, quadrados e triângulos eqüiláteros. A estrutura
de classe GeometricShapes começa com uma interface muito simples, IGeometricShape, que lista métodos comuns
para todos os três tipos de formas:
package com.example.programmingas3.geometricshapes
{
public interface IGeometricShape
{
function getArea():Number;
function describe():String;
}
}
A interface define dois métodos: o método getArea(), que calcula e retorna a área da forma, e o método describe(),
que monta uma descrição de texto das propriedades da forma.
Desejamos saber também a distância em torno do perímetro de cada forma. No entanto, o perímetro de um círculo é
chamado de circunferência, e é calculado de uma maneira exclusiva, portanto o comportamento diverge daquele de
um triângulo ou de um quadrado. Ainda há semelhança suficiente entre triângulos, quadrados e outros polígonos,
portanto faz sentido definir uma nova classe de interface só para eles: IPolygon. A interface IPolygon também é muito
simples, conforme mostrado aqui:

package com.example.programmingas3.geometricshapes
{
public interface IPolygon extends IGeometricShape
{
function getPerimeter():Number;
function getSumOfAngles():Number;
}
}
Essa interface define dois métodos comuns a todos os polígonos: o método getPerimeter() que mede a distância
combinada de todos os lados e o método getSumOfAngles() que adiciona todos os ângulos internos.
A interface IPolygon estende a interface IGeometricShape, o que significa que qualquer classe que implemente a
interface IPolygon deve declarar os quatro métodos, dois da interface IGeometricShape e dois da interface IPolygon.
Definição das classes Shape
Depois que você tiver uma boa idéia sobre os métodos comuns a cada tipo de forma, você pode definir as próprias
classes. Em termos da quantidade dos métodos precisam ser implementados, a forma mais simples é a da classe Circle,
mostrada aqui:
package com.example.programmingas3.geometricshapes
{
public class Circle implements IGeometricShape
{
public var diameter:Number;
public function Circle(diam:Number = 100):void
{
this.diameter = diam;
}
public function getArea():Number
{
// The formula is Pi * radius * radius.
var radius:Number = diameter / 2;
return Math.PI * radius * radius;
}
public function getCircumference():Number
{
// The formula is Pi * diameter.
return Math.PI * diameter;
}
public function describe():String
{
var desc:String = “This shape is a Circle.\n”;
desc += “Its diameter is ” + diameter + ” pixels.\n”;
desc += “Its area is ” + getArea() + “.\n”;
desc += “Its circumference is ” + getCircumference() + “.\n”;
return desc;
}
}
}

A classe Circle implementa a interface IGeometricShape, portanto ela deve fornecer código para os métodos
getArea() e describe(). Além disso, ela define o método getCircumference() que é exclusivo à classe Circle. A
classe Circle também declara uma propriedade, diameter que não é encontrada nas outras classes de polígonos.
Os dois outros tipos de formas, quadrados e triângulos eqüiláteros, têm algumas outras coisas em comum: cada um
deles têm lados com o mesmo comprimento e há fórmulas comuns que você pode usar para calcular o perímetro e a
soma dos ângulos internos dos dois. De fato, essas fórmulas comuns são aplicadas a todos os outros polígonos
regulares que você precisar definir no futuro.
A classe RegularPolygon é a superclasse das classes Square e EquilateralTriangle. Uma superclasse permite definir
métodos comuns em um lugar, portanto você não precisa defini-los separadamente em cada subclasse. Este é o código
da classe RegularPolygon:
package com.example.programmingas3.geometricshapes
{
public class RegularPolygon implements IPolygon
{
public var numSides:int;
public var sideLength:Number;
public function RegularPolygon(len:Number = 100, sides:int = 3):void
{
this.sideLength = len;
this.numSides = sides;
}
public function getArea():Number
{
// This method should be overridden in subclasses.
return 0;
}
public function getPerimeter():Number
{
return sideLength * numSides;
}
public function getSumOfAngles():Number
{
if (numSides >= 3)

{
return ((numSides – 2) * 180);
}
else
{
return 0;
}
}
public function describe():String
{
var desc:String = “Each side is ” + sideLength + ” pixels long.\n”;
desc += “Its area is ” + getArea() + ” pixels square.\n”;
desc += “Its perimeter is ” + getPerimeter() + ” pixels long.\n”;
desc += “The sum of all interior angles in this shape is ” + getSumOfAngles() + “
degrees.\n”;
return desc;
}
}
}
Primeiro, a classe RegularPolygon declara duas propriedades comuns a todos os polígonos regulares: o comprimento
de cada lado (a propriedade sideLength) e o número de lados (a propriedade numSides).
A classe RegularPolygon implementa a interface IPolygon e declara os quatro métodos da interface IPolygon. Ela
implementa dois desses, os métodos getPerimeter() e getSumOfAngles(), usando fórmulas comuns.
Como a fórmula do método getArea() é diferente de forma para forma, a versão da classe base do método não pode
incluir a lógica comum que pode ser herdada pelos métodos da subclasse. Em vez disso, ele simplesmente retorna um
valor padrão 0 para indicar que a área não foi calculada. Para calcular a área de cada forma corretamente, as próprias
subclasses da classe RegularPolygon precisam substituir o método getArea().
O seguinte código da classe EquilateralTriangle mostra como o método getArea() é substituído:

package com.example.programmingas3.geometricshapes
{
public class EquilateralTriangle extends RegularPolygon
{
public function EquilateralTriangle(len:Number = 100):void
{
super(len, 3);
}
public override function getArea():Number
{
// The formula is ((sideLength squared) * (square root of 3)) / 4.
return ( (this.sideLength * this.sideLength) * Math.sqrt(3) ) / 4;
}
public override function describe():String
{
/* starts with the name of the shape, then delegates the rest
of the description work to the RegularPolygon superclass */
var desc:String = “This shape is an equilateral Triangle.\n”;
desc += super.describe();
return desc;
}
}
}
A palavra-chave override indica que o método EquilateralTriangle.getArea() substitui intencionalmente o
método getArea() da superclasse RegularPolygon. Quando o método EquilateralTriangle.getArea() é
chamado, ele calcula a área usando a fórmula do código anterior, e o código no método RegularPolygon.getArea()
nunca é executado.
Em comparação, a classe EquilateralTriangle não define sua própria versão do método getPerimeter(). Quando o
método EquilateralTriangle.getPerimeter() é chamado, a chamada percorre a cadeia de herança e executa o
código no método getPerimeter() da superclasse RegularPolygon.
O construtor EquilateralTriangle() usa a instrução super() para chamar explicitamente o construtor
RegularPolygon() de sua superclasse. Se os dois construtores tivessem o mesmo conjunto de parâmetros, você
poderia omitir completamente o construtor EquilateralTriangle() e o construtor RegularPolygon() seria
executado. No entanto, o construtor RegularPolygon() precisa de um parâmetro extra, numSides. Portanto o
construtor EquilateralTriangle() chama super(len, 3) que passa o parâmetro de entrada len e o valor 3 para
indicar que o triângulo terá 3 lados.
O método describe() também usa a instrução super(), mas de uma maneira diferente, para chamar a versão da
superclasse RegularPolygon do método describe(). O método EquilateralTriangle.describe() define
primeiro a variável da string desc como uma instrução sobre o tipo da forma. Em seguida, ele obtém os resultados do
método RegularPolygon.describe() chamando super.describe() e anexa esse resultado à string desc.
A classe Square não será descrita em detalhes aqui, mas é semelhante à classe EquilateralTriangle, fornecendo um
construtor e suas próprias implementações dos métodos getArea() e describe().

Polimorfismo e o método de fábrica
Um conjunto de classes que faz bom uso de interfaces e herança pode ser usado de muitas maneiras interessantes. Por
exemplo, todas essas classes de formas descritas até agora implementam a interface IGeometricShape ou estendem
uma superclasse que o faz. Portanto, se você definir uma variável como sendo uma ocorrência de IGeometricShape,
não precisará saber se ela é realmente uma ocorrência das classes Circle ou Square para chamar seu método
describe().
O código a seguir mostra como isso funciona:
var myShape:IGeometricShape = new Circle(100);
trace(myShape.describe());
Quando myShape.describe() é chamado, ele executa o método Circle.describe(), porque embora a variável
esteja definida como uma ocorrência da interface IGeometricShape, Circle é sua classe subjacente.
Este exemplo mostra o princípio do polimorfismo em ação: a mesma chamada de método exata resulta na execução
de código diferente, dependendo da classe do objeto cujo método está sendo chamado.
O aplicativo GeometricShapes aplica esse tipo de polimorfismo com base em interface usando uma versão simplificada
de um padrão de design conhecido como método de fábrica. O termo método de fábrica faz referência a uma função
que retorna um objeto cujo tipo de dados subjacentes ou conteúdo pode ser diferente, dependendo do contexto.
A classe GeometricShapeFactory mostrada aqui define um método de fábrica denominado createShape():
package com.example.programmingas3.geometricshapes
{
public class GeometricShapeFactory
{
public static var currentShape:IGeometricShape;
public static function createShape(shapeName:String,
len:Number):IGeometricShape
{
switch (shapeName)
{
case “Triangle”:
return new EquilateralTriangle(len);
case “Square”:
return new Square(len);
case “Circle”:
return new Circle(len);
}
return null;
}
public static function describeShape(shapeType:String, shapeSize:Number):String
{
GeometricShapeFactory.currentShape =
GeometricShapeFactory.createShape(shapeType, shapeSize);
return GeometricShapeFactory.currentShape.describe();
}
}
}

O método de fábrica createShape() permite que construtores de subclasses de formas definam os detalhes das
ocorrências que eles criam, enquanto retornam os novos objetos como ocorrências de IGeometricShape para que eles
possam ser manipulados pelo aplicativo de maneira mais geral.
O método describeShape() no exemplo anterior mostra como um aplicativo pode usar o método de fábrica para
obter uma referência genérica para um objeto mais específico. O aplicativo pode obter a descrição de um objeto Circle
criado recentemente, como este:
GeometricShapeFactory.describeShape(“Circle”, 100);
Em seguida, o método describeShape() chama o método de fábrica createShape() com os mesmo parâmetros,
armazenando o novo objeto Circle em uma variável estática denominada currentShape que foi digitada como um
objeto IGeometricShape. Em seguida, o método describe() é chamado no objeto currentShape, e essa chamada é
resolvida automaticamente para executar o método Circle.describe() retornando uma descrição detalhada do
círculo.
Aprimoramento do aplicativo de amostra
O poder real das interfaces e da herança torna-se aparente quando você aprimora ou altera o aplicativo.
Suponha que você deseja adicionar uma nova forma, um pentágono, a este aplicativo de amostra. Você criaria uma
nova classe Pentagon que estende a classe RegularPolygon e define suas próprias versões dos métodos getArea() e
describe(). Em seguida, adicionaria uma nova opção de Pentagon à caixa de combinação na interface de usuário do
aplicativo. Mas isso é tudo. A classe Pentagon obteria automaticamente a funcionalidade dos métodos
getPerimeter() e getSumOfAngles() da classe RegularPolygon por herança. Como ela é herdada de uma classe que
implementa a interface IGeometricShape, uma ocorrência Pentagon também pode ser tratada como uma ocorrência
IGeometricShape. Isso significa que para adicionar um novo tipo de forma, não é preciso alterar a assinatura de
nenhum dos métodos na classe GeometricShapeFactory (e, conseqüentemente, também não é preciso alterar nenhum
código que use a classe GeometricShapeFactory).
Talvez você queira adicionar uma classe Pentagon ao exemplo de Geometric Shapes como um exercício, para ver como
as interfaces e a herança podem facilitar a carga de trabalho da adição de novos recursos a um aplicativo.

Introdução ao ActionScript 3.0


Vantagens do ActionScript 3.0
O ActionScript 3.0 vai além dos recursos de script de suas versões anteriores. Ele foi criado para facilitar a criação de
aplicativos altamente complexos com grandes conjuntos de dados e bases de código reutilizáveis orientadas a objetos.
Embora o ActionScript 3.0 não seja necessário para o conteúdo executado no Adobe Flash Player, ele permite
melhorias de desempenho que só estão disponíveis com a AVM2, a nova máquina virtual. O código do ActionScript
3.0 pode ser executado até 10 vezes mais rápido do que o código do ActionScript existente.
A versão antiga da AVM1 (ActionScript Virtual Machine) executa os códigos ActionScript 1.0 e ActionScript 2.0. As
versões 9 e 10 do Flash Player oferecem suporte a AVM1 para compatibilidade com conteúdo existente e herdado de
versões anteriores. Continuar lendo

Verificando o tamanho da base de dados no PostgreSQL


Olá, neste post irei mostrar como verificar o tamanho da base de dados no PostgreSQL.

SELECT oid,datname FROM pg_database;

Esta consulta irá retornar o OID e o respectivo nome da base de dados. Com base nestas informações iremos descobrir o tamanho ocupado pela base de dados.

Acesse o diretório onde está instalado o PostgreSQL e entre no subdiretório data/base/ (ex: /var/lib/pgsql/9.3/data/base/ no Linux)

Agora com base no OID do banco de dados obtido anteriormente verificamos o tamanho da base.

Nos sistemas Linux podemos informar o seguinte comando: du -sh <OID>/ em sistemas Windows podemos verificar com o botâo direito > Propriedades para visualizar o tamanho do diretório.

 

Até a próxima

Linux – Como encerrar processos executando em uma porta específica


Neste post irei mostrar como finalizar processos no Linux com base na porta TCP/UDP que está sendo utilizada.

Para listar os processos que estão conectados à determinada porta, podemos utilzar um destes comandos (estou assumindo a porta 8080 do protocolo TCP como exemplo):

$ lsof -w -n -i tcp:8080

$ fuser -n tcp 8080

$ netstat -anp | grep :8080

E para matar o processo é só utilizar o comando kill

$ kill -9 pid

Até a próxima

Como remover um arquivo permanentemente no Linux


Muitas vezes é necessário apagar algum arquivo e ter a certeza que ninguém vai possuir acesso às informações contidas nele, como é o caso de lista de usuários e suas respectivas senhas, números de cartões de crédito, entre outras informações sigilosas.

Nos sistemas operacionais Linux, muitos conhecem o comando “rm” que é utilizado para apagar arquivos e diretórios por linha de comando. Mas poucos sabem que esta forma de exclusão não remove o arquivo de forma permanente, pois ele permite que programas especializados em recuperar documentos obtenham tais arquivos.
Portanto, se o seu objetivo é  jamais recuperar ou permitir a recuperação do arquivo, utilize o comando shred.

$ shred -u -n <numero de interações> nome_do_arquivo

-n número de interações ou gravações

-u remove o arquivo

O comando também pode ser utilizados para apagar um HD inteiro

# shred -n <numero de interações> -z <device>

-z significa que o último padrão a ser gravado será zero, ou seja, zera tudo, incluindo o MBR;

<device>: ponto de montagem do dispositivo a ser apagado, ex: /dev/sda, /dev/hda

Para mais opções do comando, consulte o manual

$ man shred

Até a próxima

Linguagem e sintaxe do ActionScript – Parte 1


O ActionScript 3.0 consiste na linguagem central do ActionScript e na API (Application Programming Interface) do Adobe Flash Player. A linguagem principal é a parte do ActionScript que define a sintaxe da linguagem, assim como os tipos de dados de nível superior. O ActionScript 3.0 oferece acesso programático ao Flash Player.
Este post apresenta uma breve instrução à linguagem e sintaxe centrais do ActionScript. Depois de lê-lo, você terá uma noção básica de como trabalhar com tipos de dados e variáveis, como usar a sintaxe apropriada e como controlar o fluxo de dados no seu programa. Continuar lendo

Introdução do ActionScript


Olá galera, hoje darei continuação ao tutorial de actionscript, começandocom um pouco de fundamento da programação;

Fundamentos de programação

Como o ActionScript é uma linguagem de programação, para conhecê-lo, primeiro é necessário compreender alguns conceitos gerais de programação de computador. Continuar lendo

%d blogueiros gostam disto: