3

这个接口是什么意思?即使我们在一个类上实现了一个接口,每次我们在不同的类上实现它时,我们都必须一次又一次地声明它的功能,那么接口存在于 as3 或任何其他具有接口的语言上的原因是什么。谢谢

4

5 回答 5

3

我基本上同意到目前为止发布的答案,只是有一点要补充。

首先回答简单的部分,是的,其他语言也有接口。Java 立即浮现在脑海,但我很确定所有 OOP 语言(C++、C# 等)都包含一些用于创建接口的机制。

正如 Jake 所说,您可以将接口编写为“合同”,以便分离工作。假设我正在研究 A,而你正在研究 C,而 bob 正在研究 B。如果我们将 B' 定义为 B 的接口,我们可以快速且相对容易地定义 B'(相对于定义B,实施),一切照常进行。我可以假设从 AI 可以编码到 B',您可以假设从 C 可以编码到 B',当 bob 完成 B 时,我们可以将其插入。

这就是 Jugg1es 的观点。“依赖注入”使替换整个功能块的能力变得更容易(如果你不知道这个短语,请谷歌它)。这就是所描述的确切内容,您创建一个接口,该接口通常定义某事将做什么,例如数据库连接器。对于所有数据库连接器,您希望它能够连接到数据库并运行查询,因此您可以定义一个接口,说明类必须具有“connect()”方法和“doQuery(stringQuery)”。现在假设 Bob 为 MySQL 数据库编写了实现,现在您的客户说我们刚刚为新服务器支付了 200,000 美元,他们将运行 Microsoft SQL,因此要利用您的软件来利用它,您需要做的就是换掉数据库连接器。

在现实生活中,我有一个朋友在芝加哥经营一家肉类包装/分销公司。为扫描包裹和进出(库存)的物品进行软件/硬件设置的公司告诉他们,他们必须升级到更新的操作系统/服务器和更新的硬件才能与软件保持一致。该软件不是以允许它们保持向后兼容性的模块化方式编写的。我已经在这条船上很多次了,告诉某人 xyz 需要升级以获得 abc 功能,这将使我的工作变得更容易 90%。无论如何,猜测点是在现实世界中人们并不总是使用这些东西,它可能会咬你的屁股。

于 2013-03-26T20:42:12.760 回答
2

接口对 OOP 至关重要,尤其是在开发大型应用程序时。一个例子是,如果您需要一个返回数据的数据层,比如用户。如果您最终更改了数据的获取方式,例如您从 XML Web 服务数据开始,但随后切换到平面文件或其他内容,该怎么办。如果您为数据层创建了一个接口,则可以创建另一个实现它的类并对数据层进行所有更改,而无需更改应用程序层中的代码。我不知道您使用的是 Flex 还是 Flash,但是在使用 Flex 时,界面非常有用。

于 2013-03-26T19:44:34.317 回答
2

接口是定义类功能的一种方式。当您独自工作时(尤其是刚开始工作)可能没有多大意义,但是当您开始在团队中工作时,它可以帮助人们了解您的代码如何工作以及如何使用您编写的类(同时保持您的代码封装)。在我看来,这是在中间水平上考虑它们的最佳方式。

于 2013-03-26T19:49:47.613 回答
2

虽然现有的答案非常好,但我认为他们错过了在 ActionScript 中使用接口的主要优势,即您可以避免将该接口的实现编译到主文档类中。

例如,如果您有一个ISpaceShip接口,您现在可以选择做几件事来填充键入到该接口的变量。您可以加载一个外部 swf,其主文档类实现了 ISpaceShip。一旦 Loader 的contentLoaderInfoCOMPLETE 事件触发,您将其content转换为 ISpaceShip,并且它的实现(无论它是什么)永远不会编译到您的加载 swf 中。这允许您在加载过程发生时将真实内容放在用户面前。

出于同样的原因,您可以在 ISpaceShip 类型的父 AS 类中声明一个时间线实例,其中“Export for Actionscript in Frame N *un*checked. 这将在第一次使用它的帧上编译,因此您不再需要在你的预加载时间考虑这个。用足够多的东西做这个,突然你甚至不需要预加载器。

对接口进行编码的另一个优点是,如果您正在对代码进行单元测试,除非您的代码完全微不足道,否则您应该这样做。这使您能够确保代码成功或失败取决于其自身的优点,而不是基于协作者的优点,或者协作者不适合进行测试。例如,如果您有一个旨在控制特定类型 View 的控制器,您将不想为测试实例化完整视图,而只想实例化对测试产生影响的功能。

如果您在工作环境中不支持编写测试,那么对接口进行编码有助于确保您的代码在达到可以编写测试的地步后是可测试的。

于 2013-03-26T21:31:34.213 回答
1

上面的答案都非常好,我唯一要补充的是——在像 AS3 这样的语言中可能不会立即清楚,其中有几个无类型的集合类(数组、对象和字典)和对象/动态类——是这是一种按类型对不同对象进行分组的方法。

一个简单的例子:

想象一下,你有一个太空射击游戏,玩家有导弹可以锁定不同的目标。假设,为此目的,您希望任何类型的可以锁定的对象都具有用于注册它的内部函数(也称为接口):

function lockOn():void;//Tells the object something's locked onto it

function getLockData():Object;//Returns information, position, heat, whatever etc

这些目标可以是任何东西,一系列完全不相关的类别——敌人、朋友、能量提升、健康。

一种解决方案是让它们全部从包含这些方法的基类继承——但 Enemies 和 Health Pickups 在逻辑上不会共享一个共同的祖先(如果你发现自己制作了奇怪的继承链来满足你的需求,那么你应该重新考虑您的设计!),并且您的导弹还需要对其锁定的对象的引用:

var myTarget:Enemy;//This isn't going to work for the Powerup class!

或者

var myTarget:Powerup;//This isn't going to work for the Enemy class!

...但是如果所有可锁定类都实现了 ILockable 接口,则可以将其设置为类型引用:

var myTarget:ILockable;//This can be set as Enemy, Powerup, any class which implements ILockable!

..并具有上述功能作为接口本身。




它们在使用 Vector 类时也很方便(名称可能会误导您,它只是一个类型化数组) - 它们运行速度比数组快得多,但只允许单一类型的元素 - 再次,可以将接口指定为类型:

var lockTargets:Vector.<Enemy> = new Vector.<Enemy>();//New array of lockable objects

lockTargets[0] = new HealthPickup();//Compiler won't like this!

但是这个...

var lockTargets:Vector.<ILockable> = new Vector.<ILockable>();

lockTargets[0] = new HealthPickup();
lockTargets[1] = new Enemy();

将,提供EnemyHealthPickup实施ILockable,工作得很好!

于 2013-03-26T21:46:51.327 回答