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; 
}

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 palavra-chave 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.