接口

接口是方法声明的集合,以使不相关的对象能够彼此通信。例如,ActionScript 3.0 定义了 IEventDispatcher 接口,其中包含的方法声明可供类用于处理事件对象。IEventDispatcher 接口建立了标准方法,供对象相互传递事件对象。以下代码显示 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; 
}

接口的基础是方法的接口与方法的实现之间的区别。方法的接口包括调用该方法必需的所有信息,包括方法名、所有参数和返回类型。方法的实现不仅包括接口信息,而且还包括执行方法的行为的可执行语句。接口定义只包含方法接口,实现接口的所有类负责定义方法实现。

在 ActionScript 3.0 中,EventDispatcher 类通过定义所有 IeventDispatcher 接口方法并在每个方法中添加方法体来实现 IEventDispatcher 接口。以下代码摘录自 EventDispatcher 类定义:

public class EventDispatcher implements IEventDispatcher 
{ 
    function dispatchEvent(event:Event):Boolean 
    { 
        /* implementation statements */ 
    } 
 
    ... 
}

IEventDispatcher 接口用作一个协议,EventDispatcher 实例通过该协议处理事件对象,然后将事件对象传递到也实现了 IEventDispatcher 接口的其它对象。

另一种描述接口的方法是:接口定义了数据类型,就像类一样。因此,接口可以用作类型注释,也像类一样。作为数据类型,接口还可以与需要指定数据类型的运算符一起使用,如 isas 运算符。但是与类不同的是,接口不可以实例化。这个区别使很多程序员认为接口是抽象的数据类型,认为类是具体的数据类型。

定义接口

接口定义的结构类似于类定义的结构,只是接口只能包含方法但不能包含方法体。接口不能包含变量或常量,但是可以包含 getter 和 setter。要定义接口,请使用 interface 关键字。例如,接口 IExternalizable 是 ActionScript 3.0 中 flash.utils 包的一部分。IExternalizable 接口定义一个用于对对象进行序列化(即将对象转换为适合在设备上存储或通过网络传输的格式)的协议。

public interface IExternalizable 
{ 
    function writeExternal(output:IDataOutput):void; 
    function readExternal(input:IDataInput):void; 
}

IExternalizable 接口是使用 public 访问控制修饰符声明的。只能使用 publicinternal 访问控制说明符来修改接口定义。接口定义中的方法声明不能包含任何访问控制说明符。

ActionScript 3.0 遵循一种约定,其中接口名以大写字母 I 开头,不过您可以使用任何合法的标识符作为接口名。接口定义经常位于包的顶级。接口定义不能放在类定义或另一个接口定义中。

接口可扩展一个或多个其它接口。例如,下面的接口 IExample 扩展了 IExternalizable 接口:

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

实现 IExample 接口的所有类不但必须包括 extra() 方法的实现,还要包括从 IExternalizable 接口继承的 writeExternal()readExternal() 方法的实现。

在类中实现接口

类是唯一可实现接口的 ActionScript 3.0 语言元素。在类声明中使用 implements 关键字可实现一个或多个接口。下面的示例定义两个接口 IAlpha 和 IBeta 以及实现这两个接口的类 Alpha:

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

在实现接口的类中,实现的方法必须:

  • 使用 public 访问控制标识符。

  • 使用与接口方法相同的名称。

  • 拥有相同数量的参数,每一个参数的数据类型都要与接口方法参数的数据类型相匹配。

  • 使用相同的返回类型。

    public function foo(param:String):String {}

不过在命名所实现方法的参数时,您有一定的灵活性。虽然实现的方法的参数数和每个参数的数据类型必须与接口方法的参数数和数据类型相匹配,但参数名不需要匹配。例如,在上一个示例中,将 Alpha.foo() 方法的参数命名为 param

但是,将 IAlpha.foo() 接口方法中的参数命名为 str

function foo(str:String):String;

另外,使用默认参数值也具有一定的灵活性。接口定义可以包含使用默认参数值的函数声明。实现这种函数声明的方法必须采用默认参数值,默认参数值是与接口定义中指定的值具有相同数据类型的一个成员,但是实际值不一定匹配。例如,以下代码定义的接口包含一个使用默认参数值 3 的方法:

interface IGamma 
{ 
    function doSomething(param:int = 3):void; 
}

以下类定义实现 IGamma 接口,但使用不同的默认参数值:

class Gamma implements IGamma 
{ 
    public function doSomething(param:int = 4):void {} 
}

提供这种灵活性的原因是,实现接口的规则的设计目的是确保数据类型兼容性,因此不必要求采用相同的参数名和默认参数名,就能实现目标。