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.

Visão geral da linguagem

Os objetos são a base da linguagem do ActionScript 3.0, seus os blocos de construção fundamentais. Cada variável declarada, cada função escrita e cada ocorrência de classe criada é um objeto. Pense em um programa do ActionScript 3.0 como um grupo de objetos que realizam tarefas, respondem a eventos e se comunicam.
Os programadores acostumados à OOP (Programação orientada a objetos) em Java ou C++ podem pensar nos objetos como módulos que contêm dois tipos de membros: dados armazenados em variáveis ou propriedades de membros e comportamento acessível por meio de métodos. O ActionScript 3.0 define objetos de modo similar, com pequenas particularidades. No ActionScript 3.0, os objetos são apenas conjuntos de propriedades. Essas propriedades são contêineres que podem manter não apenas dados, mas também funções ou outros objetos. Se uma função for anexada a um objeto dessa forma, ela será chamada de método.
Embora a definição do ActionScript 3.0 possa parecer um pouco estranha aos programadores com experiência em Java ou C++, na prática, a definição dos tipos de objeto com classes do ActionScript 3.0 é bastante semelhante à forma como as classes são definidas em Java ou C++. A distinção entre as duas definições de objeto é importante ao discutir o modelo de objeto do ActionScript e outros tópicos avançados, mas, na maioria das situações, o termo propriedades significa variáveis de membro de classe, e não métodos. A Referência dos componentes e da linguagem do ActionScript 3.0, por exemplo, usa o termo propriedades para se referir a variáveis ou propriedades getter-setter. Ela usa o termo métodos para se referir às funções que fazem parte de uma classe.
Uma diferença sutil entre as classes no ActionScript e as classes em Java ou C++ é que, no ActionScript, as classes não são apenas entidades abstratas. As classes do ActionScript são representadas por objetos de classe que armazenam propriedades e métodos da classe. Isso permite o uso de técnicas que podem parecer estranhas aos programadores de Java e C++, como incluir instruções ou código executável no nível superior de uma classe ou um pacote.
Outra diferença entre as classes do ActionScript e as de Java ou C++ é que toda classe do ActionScript tem o que chamamos de objeto de protótipo. Nas versões anteriores do ActionScript, os objetos de protótipo, vinculados em cadeias de protótipos, serviam coletivamente como a base de toda a hierarquia de herança de classes. No ActionScript 3.0, contudo, os objetos de protótipo desempenham um papel secundário no sistema de herança. Apesar disso, eles poderão ser úteis como uma alternativa às propriedades e aos métodos estáticos se você quiser compartilhar uma propriedade e seu valor com todas as ocorrências de uma classe.

Anteriormente, os programadores de ActionScript avançados podiam manipular diretamente a cadeia de protótipos com elementos de linguagem embutidos especiais. Agora que essa linguagem fornece uma implementação mais madura de uma interface de programação baseada em classes, muitos desses elementos de linguagem especiais, como __proto__ e __resolve, não fazem mais parte da linguagem. Além disso, as otimizações do mecanismo de herança interno que fornece melhorias de desempenho significativas no Flash Player e no Adobe AIR impedem o acesso direto ao mecanismo de herança.

Objetos e classes

No ActionScript 3.0, cada objeto é definido por uma classe. Uma classe pode ser entendida como um modelo ou uma cópia de um tipo de objeto. As definições de classe podem incluir variáveis e constantes, que mantêm valores de dados, e métodos, que são funções de encapsulamento de comportamento vinculadas à classe. Os valores armazenados em propriedades podem ser valores primitivos ou outros objetos. Os valores primitivos são números, seqüências de caracteres ou valores booleanos.
O ActionScript contém diversas classes embutidas que fazem parte da linguagem central. Algumas delas, como Number, Boolean e String, representam os valores primitivos disponíveis no ActionScript. Outras classes, como Array, Math e XML, definem objetos mais complexos.
Todas as classes, incorporadas ou definidas pelo usuário, derivam da classe Object. Para os programadores com experiência no ActionScript, é importante observar que o tipo de dados Object não é mais o tipo de dados padrão, muito embora todas as outras classes ainda derivem dessa. No ActionScript 2.0, as duas linhas de código a seguir eram equivalentes porque a falta de uma anotação de tipo significava que uma variável seria do tipo Object:
var someObj:Object;
var someObj;
O ActionScript 3.0, porém, apresenta o conceito de variáveis sem tipo, que podem ser designadas destas duas formas:
var someObj:*;
var someObj;
Uma variável sem tipo não é igual a uma variável do tipo Object. A principal diferença é que as variáveis sem tipo podem manter o valor especial undefined, enquanto que uma variável do tipo Object não pode.
Você pode definir suas próprias classes usando a palavra-chave class. As propriedades de classe podem ser declaradas de três formas: as constantes podem ser definidas com a palavra-chave const, as variáveis são definidas com a palavrachave var e as propriedades getter e setter são definidas usando os atributos get e set em uma declaração de método. Os métodos podem ser declarados com a palavra-chave function.
Uma ocorrência de uma classe é criada usando o operador new. O exemplo a seguir cria uma ocorrência da classe Date chamada myBirthday.
var myBirthday:Date = new Date();

Pacotes e espaços para nomes

Os pacotes e espaços para nomes são conceitos relacionados. Os pacotes permitem compactar definições de classe juntas de uma forma que facilita o compartilhamento de dados e minimiza conflitos de nome. Os espaços para nomes permitem controlar a visibilidade de identificadores, como nomes de propriedades e métodos, e podem ser aplicados ao código quer ele resida dentro ou fora de um pacote. Os pacotes permitem organizar os arquivos de classe, e os espaços para nomes permitem gerenciar a visibilidade de propriedades e métodos individuais.

Pacotes

Os pacotes no ActionScript 3.0 são implementados com espaços para nomes, mas eles não são sinônimos. Ao declarar um pacote, você cria implicitamente um tipo especial de espaço para nomes que será conhecido em tempo de compilação. Os espaços para nomes, quando criados explicitamente, não são necessariamente conhecidos em tempo de compilação.
O seguinte exemplo usa a diretiva package para criar um pacote simples contendo uma classe:
package samples
{
public class SampleCode
{
public var sampleGreeting:String;
public function sampleFunction()
{
trace(sampleGreeting + ” from sampleFunction()”);
}
}
}
O nome da classe neste exemplo é SampleCode. Como a classe está dentro do pacote de amostras, o compilador automaticamente qualifica o nome da classe em tempo de compilação em seu nome totalmente qualificado: samples.SampleCode. O compilador também qualifica os nomes de quaisquer propriedades e métodos, para que sampleGreeting e sampleFunction() se tornem samples.SampleCode.sampleGreeting e samples.SampleCode.sampleFunction(), respectivamente.
Muitos desenvolvedores, especialmente aqueles com experiência em programação Java, podem optar por colocar apenas classes no nível superior de um pacote. O ActionScript 3.0, no entanto, oferece suporte não apenas a classes no nível superior de um pacote, mas também a variáveis, funções e até mesmo instruções. Uma utilização avançada desse recurso é definir um espaço para nomes no nível superior de um pacote de forma que fique disponível para todas as classes desse pacote. Observe, porém, que somente dois especificadores de acesso, public e internal, são permitidos no nível superior de um pacote. Diferentemente de Java, que permite declarar classes aninhadas como particulares, o ActionScript 3.0 não oferece suporte a classes aninhadas nem a particulares.
Entretanto, de muitas outras formas, os pacotes do ActionScript 3.0 são semelhantes aos pacotes na linguagem de programação Java. Como você pode ver no exemplo anterior, as referências aos pacotes totalmente qualificados são expressas usando o operador dot (.), da mesma forma que em Java. Você pode usar pacotes para organizar seu código em uma estrutura hierárquica intuitiva para ser usada por outros programadores. Isso facilita o compartilhamento de código, permitindo criar seu próprio pacote para compartilhar com outros e usar pacotes criados por outros em seu código.
O uso de pacotes também ajuda a garantir que os nomes de identificador usados sejam exclusivos e não entrem em conflito com outros. Na verdade, alguns acham que essa é a maior vantagem dos pacotes. Por exemplo, dois programadores que desejam compartilhar código entre si criam uma classe chamada SampleCode. Sem pacotes, ela cria um conflito de nome e a única solução seria renomear uma das classes. Com pacotes, porém, o conflito de nomes é facilmente evitado colocando uma classe, ou de preferência as duas, em pacotes com nomes exclusivos.
Também é possível incluir pontos incorporados no nome do pacote para criar pacotes aninhados. Isso permite criar uma organização hierárquica de pacotes. Um bom exemplo disso é o pacote flash.xml fornecido pelo ActionScript 3.0. O pacote flash.xml é aninhado dentro do pacote flash.
O pacote flash.xml contém o analisador XML herdado que era usado em versões anteriores do ActionScript. Um dos motivos para que agora ele resida no pacote flash.xml é que o nome da classe XML herdada entra em conflito com o nome da nova classe XML que implementa a funcionalidade XML da especificação ECMAScript (E4X) disponível no ActionScript 3.0.

Embora o ato de mover a classe XML herdada para um pacote seja uma boa medida inicial, a maioria dos usuários das classes XML herdadas importa o pacote flash.xml, o que irá gerar o conflito de nomes a menos que você se lembre de sempre usar o nome totalmente qualificado da classe XML herdada (flash.xml.XML). Para evitar essa situação, a classe XML herdada agora se chama XMLDocument, como mostra o seguinte exemplo:
package flash.xml
{
class XMLDocument {}
class XMLNode {}
class XMLSocket {}
}
Grande parte do ActionScript 3.0 é organizado com base no pacote flash. Por exemplo, o pacote flash.display contém a API de lista de exibição, e o pacote flash.events contém o novo modelo de eventos.

Criação de pacotes

O ActionScript 3.0 fornece uma flexibilidade significativa na forma de organizar pacotes, classes e arquivos de origem. As versões anteriores do ActionScript permitiam somente uma classe por arquivo de origem e exigiam que o nome do arquivo de origem correspondesse ao nome da classe. O ActionScript 3.0 permite incluir diversas classes em um único arquivo de origem, mas somente uma classe em cada arquivo pode ser disponibilizada para um código externo ao arquivo. Em outras palavras, somente uma classe em cada arquivo pode ser declarada dentro de uma declaração de pacote. As classes adicionais devem ser declaradas fora da definição do pacote, o que torna as classes invisíveis ao código fora do arquivo de origem. O nome da classe declarada dentro da definição do pacote deve corresponder ao nome do arquivo de origem.
O ActionScript 3.0 também oferece mais flexibilidade na forma de declarar pacotes. Nas versões anteriores do ActionScript, os pacotes simplesmente representavam diretórios nos quais os arquivos de origem eram colocados e os pacotes não eram declarados com a instrução package, mas incluíam o nome do pacote como parte do nome da classe totalmente qualificada na sua declaração de classe. Embora ainda representem diretórios no ActionScript 3.0, os pacotes podem conter mais do que apenas classes. No ActionScript 3.0, a instrução package é usada para declarar um pacote, o que significa que você também pode declarar variáveis, funções e espaços para nomes no nível superior de um pacote. É possível até incluir instruções executáveis no nível superior de um pacote. Se você declarar variáveis, funções ou espaços para nomes no nível superior de um pacote, os únicos atributos disponíveis nesse nível serão public e internal, e somente uma declaração de nível de pacote por arquivo poderá usar o atributo public, quer a declaração seja uma classe, variável, função ou um espaço para nomes.
Os pacotes são úteis para organizar o código e evitar conflitos de nome. Não confunda o conceito de pacotes com o conceito não relacionado de herança de classe. Duas classes que residem no mesmo pacote têm um espaço para nomes em comum, mas não estão necessariamente relacionadas de outra forma. Da mesma forma, um pacote aninhado pode não ter nenhuma relação semântica com o pacote pai.

importação de pacotes

Para usar uma classe que está dentro de um pacote, você deve importar o pacote ou a classe específica. Isso difere do ActionScript 2.0, em que a importação de classes era opcional.
Por exemplo, considere o exemplo de classe SampleCode apresentado anteriormente neste capítulo. Se a classe residir em um pacote chamado sample, você deverá usar uma das seguintes instruções de importação usando a classe SampleCode:
import samples.*;
ou

import samples.SampleCode;
Em geral, as instruções import devem ser tão específicas quanto possível. Se você pretende usar apenas a classe SampleCode do pacote samples, deverá importar somente a classe SampleCode e não o pacote inteiro ao qual ela pertence. A importação de pacotes inteiros pode gerar conflitos de nome inesperados.
Você também deve colocar o código-fonte que define o pacote ou a classe no caminho de classe. O caminho de classe é uma lista definida pelo usuário de caminhos de diretório locais que determina onde o compilador pesquisará as classes e os pacotes importados. O caminho de classe, às vezes, é chamado de caminho de criação ou caminho de origem.
Depois de importar adequadamente a classe ou o pacote, você pode usar o nome totalmente qualificado da classe (samples.SampleCode) ou apenas o nome da classe em si (SampleCode). Os nomes totalmente qualificados são úteis quando classes, métodos ou propriedades com nomes idênticos geram código ambíguo, mas podem ser difíceis de gerenciar se usados para todos os identificadores. Por exemplo, o uso do nome totalmente qualificado gera um código detalhado ao instanciar uma ocorrência da classe SampleCode:
var mySample:samples.SampleCode = new samples.SampleCode();
Conforme os níveis de pacotes aninhados crescem, a legibilidade do código diminui. Nas situações em que certamente não haverá identificadores ambíguos, você pode tornar seu código mais fácil de ler usando identificadores simples. Por exemplo, a instanciação de uma nova ocorrência da classe SampleCode será bem menos detalhada se você usar somente o identificador de classe:
var mySample:SampleCode = new SampleCode();
Se você tentar usar os nomes de identificador sem primeiro importar o pacote ou a classe apropriados, o compilador não conseguirá encontrar as definições de classe. Entretanto, se você importar um pacote ou uma classe, qualquer tentativa de definir um nome que entre em conflito com um nome importado irá gerar um erro.
Durante a criação de um pacote, o especificador de acesso padrão para todos os seus membros é internal, o que significa que, por padrão, os membros do pacote são visíveis apenas por outros membros do mesmo pacote. Para que uma classe fique disponível para o código fora do pacote, é necessário declará-la como public. Por exemplo, o seguinte pacote contém duas classes, SampleCode e CodeFormatter:
// SampleCode.as file
package samples
{
public class SampleCode {}
}
// CodeFormatter.as file
package samples
{
class CodeFormatter {}
}
A classe SampleCode é visível fora do pacote porque é declarada como uma classe public. A classe CodeFormatter, porém, é visível somente dentro do próprio pacote de amostras. Se você tentar acessar a classe CodeFormatter fora do pacote de amostras, irá gerar um erro, como mostra o exemplo a seguir:
import samples.SampleCode;
import samples.CodeFormatter;
var mySample:SampleCode = new SampleCode(); // okay, public class
var myFormatter:CodeFormatter = new CodeFormatter(); // error
Para que as duas classes fiquem disponíveis fora do pacote, é necessário declará-las como public. Você não pode aplicar o atributo public à declaração do pacote.

Os nomes totalmente qualificados são úteis para resolver conflitos de nome que podem ocorrer durante o uso de pacotes. Esse cenário pode surgir na importação de dois pacotes que definem classes com o mesmo identificador. Por exemplo, considere o seguinte pacote, que também tem uma classe chamada SampleCode:
package langref.samples
{
public class SampleCode {}
}
Se você importar as duas classes, como a seguir, terá um conflito de nomes ao fazer referência à classe SampleCode:
import samples.SampleCode;
import langref.samples.SampleCode;
var mySample:SampleCode = new SampleCode(); // name conflict
O compilador não tem como saber qual classe SampleCode deve usar. Para resolver o conflito, você deve usar o nome totalmente qualificado de cada classe, como a seguir:
var sample1:samples.SampleCode = new samples.SampleCode();
var sample2:langref.samples.SampleCode = new langref.samples.SampleCode();
Nota: Os programadores com experiência em C++ costumam confundir a instrução importcom #include. A diretiva #include é necessária em C++ porque os compiladores de C++ processam um arquivo por vez e não pesquisam definições de classes em outros arquivos a menos que um arquivo de cabeçalho seja incluído explicitamente. O ActionScript 3.0 tem uma diretiva include, mas não foi criado para importar classes e pacotes. Para importar classes ou pacotes no ActionScript 3.0, é necessário usar a instrução import e colocar o arquivo de origem que contém o pacote no caminho da classe.

Espaços para nomes

Os espaços para nomes fornecem controle sobre a visibilidade das propriedades e dos métodos criados. Pense nos especificadores de controle de acesso public, private, protected e internal como espaços para nomes embutidos. Se esses especificadores de controle de acesso predefinidos não atenderem às suas necessidades, você poderá definir seus próprios espaços para nomes.
Se você está familiarizado com espaços para nomes XML, boa parte desta discussão não será novidade, embora a sintaxe e os detalhes da implementação do ActionScript sejam ligeiramente diferentes do XML. Se nunca trabalhou com espaços para nomes antes, o conceito em si é simples, mas a implementação tem uma terminologia específica que você deverá aprender.
Para entender como os espaços para nomes funcionam, é bom saber que o nome de uma propriedade ou método sempre contém duas partes: um identificador e um espaço para nomes. O identificador é o que normalmente entendemos como um nome. Por exemplo, os identificadores na seguinte definição de classe são sampleGreeting e sampleFunction():
class SampleCode
{
var sampleGreeting:String;
function sampleFunction () {
trace(sampleGreeting + ” from sampleFunction()”);
}
}

Sempre que as definições não forem precedidas por um atributo de espaço para nomes, seus nomes serão qualificados pelo espaço para nomes internal padrão, o que significa que ficam visíveis apenas para os chamadores no mesmo pacote. Se o compilador estiver definido no modo estrito, o compilador emitirá um aviso de que o espaço para nomes internal se aplica a qualquer identificador sem um atributo de espaço para nomes. Para garantir que um identificador fique disponível em todo lugar, é necessário que seu nome especificamente seja precedido pelo atributo public. No código anterior, sampleGreeting e sampleFunction() têm um valor de espaço para nomes internal.
Há três etapas básicas que devem ser seguidas ao usar espaços para nomes: Primeiro, defina o espaço para nomes usando a palavra-chave namespace. Por exemplo, o código a seguir define o espaço para nomes version1:
namespace version1;
Em segundo lugar, você deve aplicar o espaço para nomes usando-o no lugar de um especificador de controle de acesso em uma declaração de propriedade ou método. O exemplo a seguir coloca uma função chamada myFunction() no espaço para nomes version1:
version1 function myFunction() {}
Por último, depois de aplicar o espaço para nomes, você pode fazer referência a ele com a diretiva use ou qualificando o nome de um identificador com um espaço para nomes. O exemplo a seguir faz referência à função myFunction() por meio da diretiva use:
use namespace version1;
myFunction();
Também é possível usar um nome qualificado para fazer referência à função myFunction(), como mostra o exemplo a seguir:
version1::myFunction();

Definição de espaços para nomes

Os espaços para nomes contêm um valor, o URI (Localizador uniforme de recursos), que às vezes é chamado de nome do espaço para nomes. Um URI permite garantir que a definição do espaço para nomes seja exclusiva.
Você cria um espaço para nomes declarando uma definição para ele de duas formas. Você pode definir um espaço para nomes com um URI explícito, assim como definiria um espaço para nomes XML, ou pode omitir o URI. O exemplo a seguir mostra como um espaço para nomes pode ser definido usando um URI:
namespace flash_proxy = “http://www.adobe.com/flash/proxy”;
O URI funciona como uma seqüência de caracteres de identificação exclusiva para o espaço para nomes. Se você omitir o URI, como no exemplo a seguir, o compilador criará uma seqüência de caracteres de identificação interna exclusiva no lugar do URI. Você não possui acesso a essa seqüência de caracteres de identificação interna.
namespace flash_proxy; Depois de definido, com ou sem um URI, o espaço para nomes não poderá ser redefinido no mesmo escopo. A tentativa de definir um espaço para nomes definido anteriormente no mesmo escopo irá gerar um erro de compilação. Se for definido dentro de um pacote ou uma classe, talvez o espaço para nomes não fique visível para o código fora do pacote ou da classe, a menos que seja usado o especificador de controle de acesso apropriado. Por exemplo, o seguinte código mostra o espaço para nomes flash_proxy definido com o pacote flash.utils. No exemplo a seguir, a falta de um especificador de controle de acesso significa que o espaço para nomes flash_proxy deve ser visível apenas para o código dentro do pacote flash.utils e não para qualquer outro código fora do pacote:
package flash.utils
{
namespace flash_proxy;
}

O código a seguir usa o atributo public para tornar o espaço para nomes flash_proxy visível para o código fora do pacote:
package flash.utils
{
public namespace flash_proxy;
}

Aplicação de espaços para nomes

Aplicar um espaço para nomes significa colocar uma definição em um espaço para nomes. As definições que podem ser colocadas em espaços para nomes incluem funções, variáveis e constantes (não é possível colocar uma classe em um espaço para nomes personalizado).
Considere, por exemplo, uma função declarada usando o espaço para nomes de controle de acesso public. O uso do atributo public em uma definição de função coloca a função no espaço para nomes público, tornando-a disponível para todo o código. Depois de definir um espaço para nomes, você pode usá-lo da mesma forma que usa o atributo public, e a definição ficará disponível para o código que pode referenciar o seu espaço para nomes personalizado. Por exemplo, se você definir um espaço para nomes example1, poderá adicionar um método chamado myFunction() usando example1 como um atributo, como mostra este exemplo:
namespace example1;
class someClass
{
example1 myFunction() {}
}
A declaração do método myFunction() usando o espaço para nomes example1 como um atributo significa que o método pertence ao espaço para nomes example1.
Tenha em mente o seguinte durante a aplicação de espaços para nomes:
• Você só pode aplicar um espaço para nomes por declaração.
• Não há como aplicar um atributo de espaço para nomes a mais de uma definição por vez. Em outras palavras, se você quiser aplicar seu espaço para nomes a dez funções diferentes, deverá adicioná-lo como um atributo a cada uma das dez definições de função.
• Se aplicar um espaço para nomes, também não será possível definir um especificador de controle de acesso porque espaços para nomes e especificadores de acesso são mutuamente exclusivos. Ou seja, não é possível declarar uma função ou propriedade como public, private, protected ou internal e aplicar o espaço para nomes.

Referência a espaços para nomes

Não é necessário fazer referência a um espaço para nomes explicitamente durante o uso de um método ou uma propriedade declarados com qualquer um dos espaços para nomes de controle de acesso, como public, private, protected e internal. Isso porque o acesso a esses espaços para nomes especiais é controlado por contexto. Por exemplo, as definições colocadas no espaço para nomes private ficam disponíveis automaticamente para o código dentro da mesma classe. Para os espaços para nomes que você definir, porém, essa diferenciação de contexto não existe. Para usar um método ou uma propriedade colocados em um espaço para nomes personalizado, é necessário fazer referência ao espaço para nomes.
Você pode fazer referência a espaços para nomes com a diretiva use namespace ou pode qualificar o nome com o espaço para nomes usando o pontuador do qualificador de nome (::). A referência a um espaço para nomes com a diretiva use namespace “abre” o espaço para nomes, para que ele possa ser aplicado a quaisquer identificadores não qualificados. Por exemplo, se definir o espaço para nomes example1, você poderá acessar seus nomes usando use namespace example1:

use namespace example1;
myFunction();
É possível abrir mais de um espaço para nomes por vez. Quando aberto com use namespace, o espaço para nomes permanece aberto em todo o bloco de código no qual se encontra. Não há como fechar explicitamente um espaço para nomes.
O uso de mais de um espaço para nomes, contudo, aumenta a probabilidade de conflitos de nome. Se preferir não abrir um espaço para nomes, você poderá evitar a diretiva use namespace qualificando o nome do método ou da propriedade com o espaço para nomes e o pontuador do qualificador de nome. Por exemplo, o seguinte código mostra como qualificar o nome myFunction() com o espaço para nomes example1:
example1::myFunction();

Uso de espaços para nomes

Um exemplo real de um espaço para nomes usado para evitar conflitos de nome é a classe flash.utils.Proxy que faz parte do ActionScript 3.0. A classe Proxy, que é a substituição para a propriedade Object.__resolve do ActionScript 2.0, permite interceptar diferenças em propriedades ou métodos não definidos antes da ocorrência de um erro. Todos os métodos da classe Proxy residem no espaço para nomes flash_proxy para evitar conflitos de nome.
Para entender melhor como o espaço para nomes flash_proxy é usado, é preciso entender como usar a classe Proxy.
A funcionalidade da classe Proxy está disponível somente para suas classes herdadas. Em outras palavras, se quiser usar os métodos da classe Proxy em um objeto, a definição de classe do objeto deve estender a classe Proxy. Por exemplo, para interceptar as tentativas de chamar um método não definido, é necessário estender a classe Proxy e substituir seu método callProperty().
Você deve se lembrar de que a implementação de espaços para nomes, em geral, é um processo de três etapas: definir, aplicar e referenciar um espaço para nomes. Como os métodos da classe Proxy nunca são chamados explicitamente, o espaço para nomes flash_proxy é definido e aplicado, mas não referenciado. O ActionScript 3.0 define o espaço para nomes flash_proxy e o aplica na classe Proxy. O código precisa apenas aplicar o espaço para nomes flash_proxy às classes que estendem a classe Proxy.
O espaço para nomes flash_proxy é definido no pacote flash.utils de forma semelhante à seguinte:
package flash.utils
{
public namespace flash_proxy;
}
O espaço para nomes é aplicado aos métodos da classe Proxy como mostrado no seguinte trecho dessa classe:
public class Proxy
{
flash_proxy function callProperty(name:*, … rest):*
flash_proxy function deleteProperty(name:*):Boolean

}
Como mostra o código a seguir, primeiro você deve importar a classe Proxy e o espaço para nomes flash_proxy.
Depois, deve declarar sua classe de forma que estenda a classe Proxy (você também deve adicionar o atributo dynamic se estiver compilando no modo estrito). Ao substituir o método callProperty(), o espaço para nomes flash_proxy deve ser usado.

package
{
import flash.utils.Proxy;
import flash.utils.flash_proxy;
dynamic class MyProxy extends Proxy
{
flash_proxy override function callProperty(name:*, …rest):*
{
trace(“method call intercepted: ” + name);
}
}
}
Se criar uma ocorrência da classe MyProxy e chamar um método não definido, tal como o método testing() chamado no exemplo a seguir, seu objeto Proxy irá interceptar a chamada de método e executar as instruções dentro do método callProperty() (neste caso, uma instrução trace() simples).
var mySample:MyProxy = new MyProxy();
mySample.testing(); // method call intercepted: testing
Há duas vantagens em ter os métodos da classe Proxy dentro do espaço para nomes flash_proxy. Primeiro, ter um espaço para nomes separado reduz a desordem na interface pública de qualquer classe que estende a classe Proxy. (Há aproximadamente uma dúzia de métodos na classe Proxy que podem ser substituídos e nenhum foi criado para ser chamado diretamente. Colocá-los no espaço para nomes público poderia gerar confusão.) Em segundo lugar, o uso do espaço para nomes flash_proxy evita os conflitos de nome caso a subclasse Proxy contenha métodos de ocorrência com nomes que correspondem a qualquer método da classe Proxy. Por exemplo, você pode querer chamar um de seus métodos de callProperty(). O código a seguir é aceitável, porque sua versão do método callProperty() está em um espaço para nomes diferente:
dynamic class MyProxy extends Proxy
{
public function callProperty() {}
flash_proxy override function callProperty(name:*, …rest):*
{
trace(“method call intercepted: ” + name);
}
}
Os espaços para nomes também podem ser úteis para fornecer acesso a métodos ou propriedades de uma forma que não seria possível com os quatro especificadores de controle de acesso (public, private, internal e protected).
Por exemplo, você pode ter alguns métodos utilitários espalhados em vários pacotes. Você quer disponibilizar esses métodos para todos os pacotes, mas não quer que sejam públicos. Para fazer isso, você pode criar um novo espaço para nomes e usá-lo como seu próprio especificador de controle de acesso especial.
O exemplo a seguir usa um espaço para nomes definido pelo usuário para agrupar duas funções que residem em pacotes diferentes. Ao agrupá-las no mesmo espaço para nomes, você pode tornar as duas funções visíveis para uma classe ou um pacote por meio de uma única instrução use namespace.
Este exemplo usa quatro arquivos para demonstrar a técnica. Todos os arquivos devem estar no caminho de classe. O primeiro deles, myInternal.as, é usado para definir o espaço para nomes myInternal. Como o arquivo está em um pacote chamado example, você deve colocá-lo em uma pasta chamada example. O espaço para nomes é marcado como public para que possa ser importado para outros pacotes.

// myInternal.as in folder example
package example
{
public namespace myInternal = “http://www.adobe.com/2006/actionscript/examples”;
}
O segundo e terceiro arquivos, Utility.as e Helper.as, definem as classes que contêm os métodos que devem estar disponíveis para outros pacotes. A classe Utility é um pacote example.alpha, o que significa que o arquivo deve ser colocado dentro de uma pasta chamada alpha, que é uma subpasta da pasta example. A classe Helper é um pacote example.beta, o que significa que o arquivo deve ser colocado dentro de uma pasta chamada beta, que também é uma subpasta da pasta example. Os dois pacotes, example.alpha e example.beta, devem importar o espaço para nomes antes de usá-lo.
// Utility.as in the example/alpha folder
package example.alpha
{
import example.myInternal;
public class Utility
{
private static var _taskCounter:int = 0;
public static function someTask()
{
_taskCounter++;
}
myInternal static function get taskCounter():int
{
return _taskCounter;
}
}
}
// Helper.as in the example/beta folder
package example.beta
{
import example.myInternal;
public class Helper
{
private static var _timeStamp:Date;
public static function someTask()
{
_timeStamp = new Date();
}
myInternal static function get lastCalled():Date
{
return _timeStamp;
}
}
}

O quarto arquivo, NamespaceUseCase.as, é a classe de aplicativo principal e deve ser uma irmã da pasta example. No Adobe Flash CS4 Professional, essa classe deveria ser usada como a classe de documento para o FLA. A classe NamespaceUseCase também importa o espaço para nomes myInternal e o usa para chamar os dois métodos estáticos que residem nos outros pacotes. O exemplo usa métodos estáticos apenas para simplificar o código. Os métodos estáticos e de ocorrência podem ser colocados no espaço para nomes myInternal.
// NamespaceUseCase.as
package
{
import flash.display.MovieClip;
import example.myInternal; // import namespace
import example.alpha.Utility;// import Utility class
import example.beta.Helper;// import Helper class
public class NamespaceUseCase extends MovieClip
{
public function NamespaceUseCase()
{
use namespace myInternal;
Utility.someTask();
Utility.someTask();
trace(Utility.taskCounter); // 2
Helper.someTask();
trace(Helper.lastCalled); // [time someTask() was last called]
}
}
}

Este é o final da primeira parte do post de linguagem e sintaxe do action script.

Até mais.

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s