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 não é necessariamente visível quando você grava pequenos scripts que contêm apenas alguns objetos que interagem entre si. No entanto, à medida que aumenta o escopo de um programa, o número de objetos que devem ser gerenciados também sobe. Nesse caso, as classes permitem controlar melhor como os objetos são criados e como interagem uns com os outros.
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 só não continua a oferecer suporte às palavras-chaves introduzidas no ActionScript 2.0. Ele também acrescenta novos recursos. Por exemplo, o ActionScript 3.0 inclui um controle de acesso aprimorado com os atributos protected e internal. Além disso, fornece um melhor controle sobre a herança com as palavras-chave final e override.
Para os desenvolvedores que criaram classes em linguagens de programação como Java, C++ ou C#, o ActionScript oferece uma experiência parecida. O ActionScript compartilha muitas das mesmas palavras-chaves e nomes de atributos, como class, extends e public.
Nota: Na documentação do Adobe ActionScript, 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, aqui esses termos são distintos. Por exemplo, a expressão "propriedades de classe" é usada para indicar todos os membros de uma classe, em vez de apenas membros estáticos.
Definições de classesAs definições de classes do ActionScript 3.0 usam sintaxe semelhante à sintaxe 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 classesO ActionScript 3.0 permite modificar definições de classe usando um dos quatro seguintes atributos:
Atributo
|
Definição
|
dynamic
|
Permitir que propriedades sejam adicionadas a ocorrências em tempo de execução.
|
final
|
Não deve ser estendido por outra classe.
|
internal (padrão)
|
Visível para referências dentro do pacote atual.
|
public
|
Visível para referências em todos os lugares.
|
Para cada um desses atributos, exceto para internal, você inclui explicitamente o atributo para obter o comportamento associado. Por exemplo, se você não incluir o atributo dynamic ao definir uma classe, você não pode 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. 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 adiciona automaticamente o atributo internal para você. Você também pode definir uma classe para ser apenas visível dentro do arquivo de origem no qual está definido. Coloque a classe na parte de baixo do seu arquivo de origem, abaixo da chave de fechamento da definição de pacote
Corpo da classeO corpo da classe está dentro de chaves. Ele define as variáveis, constantes e métodos de sua classe. O exemplo a seguir mostra a declaração para a classe Accessibility no ActionScript 3.0:
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. As instruções que estão dentro do corpo da classe, mas fora de uma definição de método, são executadas exatamente uma vez. Essa execução acontece quando a definição de 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
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 classesEm 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. No entanto, no Adobe ActionScript 3.0 Reference for the Adobe Flash Platform, o termo é usado de forma mais estreita. Nesse contexto, o termo propriedade inclui apenas os membros de classe 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.
Atributo
|
Definição
|
internal (padrão)
|
Visível para referências dentro do mesmo pacote.
|
private
|
Visível para referências na mesma classe.
|
protected
|
Visível para referências na mesma classe e em classes derivadas.
|
public
|
Visível para referências em todos os lugares.
|
static
|
Especifica que uma propriedade pertence à classe, ao contrário das ocorrências da classe.
|
UserDefinedNamespace
|
Nome do espaço para nomes personalizado definido pelo usuário.
|
Atributos de espaço para nomes de controle de acessoO 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 código a seguir cria uma classe simples denominada PrivateExample com uma variável private, e tenta acessar a variável private de fora da classe.
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):
|
modo Estrito
|
modo Padrão
|
operador ponto (.)
|
erro em tempo de compilação
|
erro em tempo de execução
|
operador colchete ([])
|
erro em tempo de execução
|
erro em tempo de execução
|
Em classes declaradas com o atributo dynamic, as tentativas de acessar uma variável private não resulta em um erro em tempo de execução. Em vez disso, a variável não é visível, por isso o valor undefined é devolvido. 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:
|
modo Estrito
|
modo Padrão
|
operador ponto (.)
|
erro em tempo de compilação
|
undefined
|
operador colchete ([])
|
undefined
|
undefined
|
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 aqueles familiarizados 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 em Java. Ele difere na medida em que a versão em Java também permite o acesso aos chamadores no 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:
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 staticO 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árioComo 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áveisAs 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 palavra-chave 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áticasAs 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 gera 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ênciaAs variáveis de ocorrência incluem propriedades declaradas com as palavras-chave var e const, mas sem a palavra-chave 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étodosMé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. Como ocorre com qualquer propriedade de classe, você pode aplicar qualquer um dos atributos de propriedade de classe aos métodos, incluindo private, protected, public, internal, static ou custom namespace. Você pode usar uma instrução de função como a seguinte:
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, use 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 (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 dificulta a leitura do código 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 construtorOs métodos de construtor, às vezes chamados 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 comporta 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 cria automaticamente um construtor vazio. Se a classe estender outra classe, o compilador inclui uma chamada super() no construtor gerado.
Métodos estáticosOs 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ênciaMé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 acessar a 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 acessar a 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 setAs 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, ocorre 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 vinculadosUm 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 representa o objeto ou a 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 classesEnumeraçõ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 palavra-chave 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 os valores"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 de string do dia.
Classes de ativos incorporadosO 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 está disponível em tempo de execução, mas ao custo do tamanho do arquivo SWF aumentado.
Uso de classes de ativos incorporados no Flash ProfessionalPara 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();
Como alternativa, você pode usar a tag de metadados [Embed] para incorporar os ativos a um projeto do Flash Professional, conforme descrito a seguir. Se você usar a tag de metadados [Embed] no seu código, o Flash Professional usa o compilador do Flex para compilar seu projeto no lugar do compilador do Flash Professional.
Uso de classes de ativos incorporadas com o compilador do FlexSe estiver compilando seu código com o compilador do Flex, para incorporar um ativo no código do ActionScript, use a tag de metadados [Embed]. Coloque o ativo na pasta de origem principal ou em outra pasta que esteja no caminho de criação do projeto. Quando o compilador do Flex encontra uma tag de metadados Embed, ele cria a classe de ativos incorporada para você. É possível acessar a classe por meio de uma variável de tipo de dados Class que você declara imediatamente depois da tag de metadados [Embed]. Por exemplo, o código a seguir incorpora um som denominado sound1.mp3 e usa uma variável denominada soundCls para armazenar uma referência na classe de ativo incorporado associada a esse som. Em seguida, o exemplo cria uma ocorrência da classe de ativo incorporado e chama o método play() nessa ocorrência:
package
{
import flash.display.Sprite;
import flash.media.SoundChannel;
import mx.core.SoundAsset;
public class SoundAssetExample extends Sprite
{
[Embed(source="sound1.mp3")]
public var soundCls:Class;
public function SoundAssetExample()
{
var mySound:SoundAsset = new soundCls() as SoundAsset;
var sndChannel:SoundChannel = mySound.play();
}
}
}
Adobe Flash BuilderPara usar a tag de metadados [Embed] em um projeto ActionScript do Flex Builder, importe todas as classes necessárias da estrutura do Flex. Por exemplo, para incorporar sons, importe a classe mx.core.SoundAsset. Para usar a estrutura do Flex, inclua o arquivo framework.swc no caminho de criação do ActionScript. Isso aumenta o tamanho do arquivo SWF.
Adobe FlexComo alternativa, no Flex você pode incorporar um ativo com a diretiva @Embed() em uma definição de tag MXML.
|
|