`

AS3接口的一个很重要的作用

阅读更多

 

最近在做一些AS3项目,有两大问题让我感觉比较头痛的。一是垃圾回收器。由于AS3垃圾回收机制跟AS2有质的区别,但是做的时候又没有了解过这个问题,做了大半才知道,实现AS3的垃圾回收还需要在开发前做好一个相关的架构......这个有位据说是举世闻名的架构师写了相关文章......可惜我哪怕看懂了还是要重写很多东西......另一个则是我在这篇文章要说的接口,虽然在目前的项目里还不是特别需要用上,但是,一直都有人强调接口在OOP里的重要性,但是无论是上网查资料还是看书,都似乎是要让我浅尝辄止,讲的大多都是规范化编程,利于团队合作......

然而,实际上,说这个的作用MS不能很好地说明接口的必要性,要是这么解释的话,即使不存在接口,程序照样可以正常运行。接口只是给编译器检验的时候多设了一道关卡。而且这个关卡并没有太实质的作用。呵呵,尽管BS我吧,我还没参与过团队开发(当然,跟美工,后台程序员的那种合作不计算在内)。AS3中另一个作为编译器的关卡语法override则让我觉得对于避免运行时错误起到举足轻重的作用。

又不知道在什么地方听说了类对接口有很大的依赖性,为此,我痛下决心,非要研究出点东西来。研究过程发现,研究接口的问题很像研究哲学问题。

直觉告诉我,黑羽应该早研究出来,并把成果发布在了《ActionScript 3 殿堂之路》一书上,可惜的是,习惯于使用帮助文件和百度,Google的我,到目前还是犹豫不决,该不该再买他的书来看,所以,本人在此要对黑羽表示万分的抱歉。

帮助文件对接口的解释跟AS2里的说法没有什么两样,有些专门讲述AS2和AS3转换的技术文档也没有提及,令我感到相当郁闷。

在通过搜索引擎查找到的几篇文章(成千上万的搜索结果基本上都是同一篇文章的......)中,写的都跟我之前的理解没有什么两样。不过,我在搜索的过程中,发现了还有不少文章在比较抽象类和接口。不过,由于AS3不能自定义抽象类,文章都是讲Java的,也就先跳过了。

终于给我找到一篇似乎讲到了一些我之前不知道的内容。

http://www.kelew.com/?p=43

这里讲到了一点是方便通讯,并且可以实现代码提示。哦~这是Flex里的问题吧。Flash的自定义类还是没有代码提示的。但是Flex里有(Flex在我的机上存活过两天,所以我对Flex只有一点感性认识),这文章说转成接口就会有代码提示,那就是说,一个变量可以转换为接口的类型,不一定是类啦(哎呀,现在才知道,为什么以前的编译器错误总提示无法加载类或接口了,原来可以这么转换的)。

确实,在AS3里,是可以写成(xx as IEventDispatcher)的。于是,我的研究就进了一步。还可以写成var xx:IEventDispatcher,不过不能实例化,就是不可以写成new IEventDispatcher()。

我是一个对生活没啥理解的人,所以,我也懒得想着用生活中的什么例子来继续解释下面的问题了,就拿Flash本身来说好了。(写到后面发现自己想到一个实际的例子了,如果这里看不下去,可以先看后面的部分,就是____________后面的内容)

在Flash的IDE里,你可以绘制形状,添加文本,添加元件(图形,按钮,MC)。

先拿形状和文本来说,形状和文本你都可以设置填充颜色,然后形状还可以设置线条颜色与粗细。那么,如果要你开发这样一个软件,也是可以创建形状和文本的话,你就可以有两个方法来创建共同的东西。

一个就是使用继承。比方说,你可以先创建一个颜色处理器的类。

 

 

 

package {
	public class colorProcessor {
		public function setFillColor(color:uint):void {
		}
	}
}

 

 

然后,形状和文本就可以继承colorProcessor类了。

 

 

package {
	public class shapeClass extends colorProcessor {
		override public function setFillColor(color:uint):void {
			//....
		}
		//由于还可以设置线条,你可以在这里新加一个方法
		public function setLineColor(color:uint):void {
			//....
		}
	}
}
package {
	public class textClass extends colorProcessor {
		override public function setFillColor(color:uint):void {
			//....
		}
	}
}

 

 

 

因为对文本和对形状的填充颜色设置可能会采用不同的实现方法,比方说,中国人吃饭和外国人吃饭都是吃饭,但是中国人可能用筷子,外国人则用刀叉。所以,在colorProcessor里,setFillColor就没有包含方法的实现了,给被继承的类自我扩充。

第二种方法,使用接口。把colorProcessor写成接口。

 

 

 

package {
	public interface IColorProcessor {
		function setFillColor(color:uint):void;
	}
}

 

 

然后形状和文本类则改成

 

 

package {
	public class shapeClass implements IColorProcessor {
		public function setFillColor(color:uint):void {
			//....
		}
		//由于还可以设置线条,你可以在这里新加一个方法
		public function setLineColor(color:uint):void {
			//....
		}
	}
}
package {
	public class textClass implements IColorProcessor {
		public function setFillColor(color:uint):void {
			//....
		}
	}
}

 

 

 

这么看起来,colorProcessor类和IColorProcessor接口没有太大区别。这两个都声明了方法,也没有包含方法的实现。使用继承父类的,则通过覆盖方法来实现被继承类的方法,而实现接口的则在接口实现的类里写出了方法的实现。像colorProcessor里这种只声明方法,里面实际上没有方法实现的类,实际上是运用了抽象类的思想。不过,在AS3里尚不可自定义抽象类,所以,所谓的抽象类也只是有形无实。真正的抽象类跟接口一样,不能实例化,而且,继承者必须覆盖抽象类的所有方法才可以实例化(所以这点跟接口也很相似)。AS3有内置的抽象类如DisplayObjectContainer,大家可以尝试去用来测试实例化,继承的可行性。

说到这里,其实还是没有说明接口存在的必要性。显然,上面的形状和文本类,即使没有“抽象类”和接口,两个类照样可以正常运行。但是,假若现在加入了MC,MC不具备设置颜色的属性,那么,在Flash的IDE下,你使用颜料桶工具将无法对MC进行颜色填充,如果你要开发一个Flash的IDE,那么,你就将要对你选中的对象进行判断,它是文本,形状,还是MC。

在AS3里,与对象类型有关的运算主要有以下几种:

getQualifiedClassName

getQualifiedSuperclassName

is

instanceof(还是推荐用is代替)

as

 

getQuailiedClassName可以获取该对象的类型,返回的是类名。假若my_txt是文本,my_shape是形状,那么,就有

getQualifiedClassName(my_txt)将返回textClass

getQualifiedClassName(my_shape)将返回shapeClass

那么,在仅有这三种对象存在,并且该三种对象没有扩展的时候,判断被选定对象可以用if或者switch,如

 

 

 

switch (getQuailiedClassName(currentObj)) {
	case "shapeClass" :
	case "textClass" :
		currentObj.setFillColor(newColor);
		break;
	case "mcClass" :
		//do nothing
		break;
}

 

 

但是,文本还可以有动态文本,静态文本,输入文本等子类,形状可能有矩形,圆形等子类,那么,你目前还是有办法可以处理这个问题:

 

 

switch (getQuailiedClassName(currentObj)) {
	case "shapeClass" :
	case "textClass" :
	case "triangleClass" :
	case "rectangleClass" :
	case "dynamicTextClass" :
	case "staticTextClass" :
	case "inputTextClass" :
		currentObj.setFillColor(newColor);
		break;
	case "mcClass" :
		//do nothing
		break;
}

 

 

 

多麻烦啊~而且当继承结构复杂的时候,都不知道该写多少句了。因此,getQualifiedSuperclassName就在这里起了点作用。可以检查其超类是否为shapeClass或者textClass。

但是,这个函数只能检查到上一级的类名,若继承结构复杂,可能有的继承两至三级甚至更多,在不知道继承级别的情况下,用getQualifiedSuperclassName想知道对象的继承关系链里是否存在textClass或者shapeClass,就只能通过遍历至顶级类来检验了......不但麻烦,而且效率低。

is运算符诞生啦!这一运算符可以检验某对象是否为指定类的实例,只要指定类在继承关系链中,都返回true。另外也包括接口。也就是说,假设my_spr是一个Sprite类的实例,那么下面的三个表达式都输出true

trace(my_spr is Sprite);

trace(my_spr is DisplayObjectContainer);

trace(my_spr is IEventDispatcher);

回到刚才说的那个选定对象的问题。假设舞台上现在既有MC,又有形状,也有文本。而且形状有圆形,矩形等子类的实例,文本有静态文本和动态文本。那么,当选定一个对象时,要确定该对象是否具有颜色填充的功能,就可以将上面的代码简化为:

 

 

 

if ((currentObj is textClass) || (currentObj is shapeClass)) {
	currentObj.setFillColor(newColor);
} else if (currentObj is mcClass) {
}//do nothing
}

 

 

 

代码得到了简化,可惜的是,其适应性还是相当有限,如果可以进行颜色填充的类也有很多,不止textClass和shapeClass的话,此段代码还是要重复写很多很长的“排比句”。

这时,接口起到了作用。因为textClass和shapeClass都是IColorProcessor的接口实现类,所以,按照is的运算规则,上面的代码就可以简化成

 

 

 

if ((currentObj is IColorProcessor)) {
	currentObj.setFillColor(newColor);
} else if (currentObj is mcClass) {
}//do nothing
}

 

 

 

那么,只要具有填充颜色功能的类都实现IColorProcessor接口,就返回true,就可以进行颜色填充,而不需要再检查具体是什么类实现该接口了,也不用考虑继承关系,多方便。

既然如此,那么为什么不能用“抽象类”代替接口呢?如果textClass和shapeClass都继承colorProcessor类,然后检查currentObj is colorProcessor不也一样嘛?接口有何种特性是抽象类不具备的呢?

 

至此,我终于没办法了,要翻Java的技术文章来看,了解下接口和抽象类的区别所在。

在我所看到的文章中,貌似都认为抽象类的优势比接口还大,不过却推荐使用接口,而不用抽象类。看到那些文章后面的地方,终于茅塞顿开啦~~

在讲接口的优势之前,我先继续刚才的Flash IDE开发问题。

现在,假设你开发到Flash 8,要添加上滤镜功能,但是滤镜只可以加在文本和MC上,那么,你可以先定义一个“抽象类”:

 

 

 

package {
	public class filterProcessor {
		public function setFilters(filt_arr:Array):void {
		}
	}
}

 

 

然后由mcClass来继承:

 

 

package {
	public class mcClass extends filterProcessor {
		override public function setFilters(filt_arr:Array):void {
		}
	}
}

 

 

 

至于文本,同样地,可以用:

 

 

 

package {
	public class textClass extends filterProcessor {
		override public function setFilters(filt_arr:Array):void {
		}
	}
}

 

 

文本这里就出问题了,这么写,之前文本继承的colorProcessor类就没有了。但是,在AS3里,你不能这么写:

 

 

package{
	public class textClass extends filterProcessor extends colorProcessor{
		override public function setFilters(filt_arr:Array):void{
		}
	}
}
 

 

也不可以写成:

 

 

package{
	public class textClass extends filterProcessor,colorProceessor{
		override public function setFilters(filt_arr:Array):void{
		}
	}
}
 

 

 

那么,如果想同时继承这两个类,该怎么办呢?你不可以说先让colorProcessor和filterProcessor相互继承,假如颜色处理器继承了滤镜处理器,那将意味着,形状也可以设置滤镜(这就错掉啦)。如果反过来,就会导致MC可以进行颜色填充(也不行啊)。

 

在这种情况下,接口的优势就体现出来啦。

原来,接口和抽象类相比,多出的一个优势在于(仅限Java和AS3),一个类可以实现多个接口,但是不能继承多个类。所以,如果在这里改用接口,就一切都好解决了。先定义两个接口:

 

 

 

package {
	public interface IColorProcessor {
		function setFillColor(color:uint):void;
	}
}
package {
	public interface IFilterProcessor {
		function setFilters(filt_arr:Array):void;
	}
}
 

 

然后,形状,文本和MC就分别用如下的方式实现接口:

 

 

package {
	public class shapeClass implements IColorProcessor {
		public function setFillColor(color:uint):void {
		}
	}
}
package {
	public class textClass implements IColorProcessor,IFilterProcessor {
		public function setFillColor(color:uint):void {
		}
	}
}
package {
	public class mcClass implements IFilterProcessor {
		public function setFillColor(color:uint):void {
		}
	}
}

 

 

 

这样实现了接口以后,在舞台上假如形状,MC,文本都存在的话,你也不需要检查他们是什么类了,只要了解他们实现的接口就OK。

 

 

 

if (currentObj is IColorProcessor) {
	currentObj as IColorProcessor.setFillColor(newColor);
}
if (currentObj is IFilterProcessor) {
	currentObj as IFilterProcessor.setFilters(filt_arr);
}

 

 

可见,定义了接口,在处理多种类型的对象过程中会方便很多(可能有人会说,假若方法真的不存在,用try...catch不一样可以处理掉嘛.....,不过......用这样的处理错误方法,在对象多的时候,运行起来的状况会怎样呢?)。从研究接口用处的过程中,我们发现,接口的产生其实是源于Java和AS3对类多态(多继承)的限制。为了可以更好地对类的特性进行描述,判断处理,接口就显得相当有必要了。

 

 

 

讲到现在,我发现自己似乎还没有讲明白问题。但是这个时候我MS已经想到了一个更为实际的例子:

刚讲了中国人和外国人都继承了人类,现在,假设要对中国人和外国人再一次进行分类,都按性别再分别对中国人和外国人进行分类。假如全部用类来做的话,就是先有一个最顶级的人类,接着就是中国人类和外国人类,男人类和女人类,接着就是中国男人,中国女人,外国男人,外国女人。

前面说了,AS3和Java不能继承多个类(前面没看的也没关系,现在你知道就可以了)。所以,你的继承可以有两种策略,不过,顶级的人类是无可争议的了。

 

 

 

package {
	public class person {
	}
}

 

 

然后,第一种策略,就是先把人类分成中国人和外国人:

 

 

package {
	public class Chinese extends person {
	}
}
package {
	public class Foreigner extends person {
	}
}

 

 

接着再把他们分别分成男和女的:

 

 

package {
	public class Chinese_man extends Chinese {
	}
}
package {
	public class Chinese_woman extends Chinese {
	}
}
package {
	public class Foreign_man extends Foreigner {
	}
}
package {
	public class Foreign_woman extends Foreigner {
	}
}

 

 

第二种策略,跟第一种策略相反。先按性别分,再按地区分:

 

 

package {
	public class man extends person {
	}
}
package {
	public class woman extends person {
	}
}

 

 

接下来的就是

 

 

package {
	public class Chinese_man extends man {
	}
}
package {
	public class Chinese_woman extends woman {
	}
}
package {
	public class Foreign_man extends man {
	}
}
package {
	public class Foreign_woman extends woman {
	}
}

 

 

 

现在分好了,开始要让他们做两件事情:

1 让外国人在中国环游一周;

2 组织全体女性到联合国的妇联开会。

 

按照第一种策略的话,让外国人在中国环游一周,就只需要让所有外国人类的实例都调用一个环游的方法就可以了。但是,若要完成第二个任务,就需要先对中国的女性调用一个组织开会的方法,再对外国女性调用一个组织开会的方法。相反,第二种策略就让第一个任务完成得比较麻烦,第二个任务就相对方便。鱼和熊掌,两者不可兼得。

 

但是,如果使用接口呢?情况就大大不同。

在定义了人的接口以后:

 

 

 

package {
	public interface IPerson {
	}
}

 

 

再定义四个接口:男人,女人,中国人,外国人:

 

 

package{
	public interface IMan extends IPerson{
	}
}
package{
	public interface IWoman extends IPerson{
	}
}
package{
	public interface IForeigner extends IPerson{
}
package{
	public interface IChinese extends IPerson{
	}
}

 

 

接下来就定义中国男人,中国女人,外国男人,外国女人。这时可以用类了。

 

 

package {
	public class Chinese_man implements IMan,IChinese {
	}
}
package {
	public class Chinese_woman implements IWoman,IChinese {
	}
}
package {
	public class Foreign_man implements IMan,IForeigner {
	}
}
package {
	public class Foreign_woman implements IWoan,IForeigner {
	}
}

 

 

同样完成上面的两个任务,第一个,只需要调用实现接口IForeigner的类就OK了,同样地,第二个也只需要调用实现接口IWoman的类。当分区分细,不再按中国人外国人分类,而要按照国籍来分成200多个类的时候,或者再细分至省和洲的时候,这一做法的优势就更为明显了。

 

总结起来,可以得知,在类的继承结构不能仅用树状去表示,如上面的具有交叉继承结构的时候,就建议用接口了。但是,如果是简单的树状结构,我觉得还是用类继承好些,毕竟这样的做法也有维护上的优势。

下面画两个示意图说明接口和类(“抽象类”)的适用情况。

此种情况适合用接口:

 

 

类继承适合于此种情况:

 

分享到:
评论

相关推荐

    FPGA中AS和JTAG接口的使用

    此外,还有一个可选的TRST(Test Reset)引脚,用于复位JTAG接口。JTAG接口的主要优点是能够实现在线编程和调试,它允许用户在电路板上对FPGA进行编程和故障排查,无需拆卸器件,大大提高了工作效率。 JTAG不仅用于...

    as3 接口类的用法和好处

    尽管抽象类也能提供类似接口的功能,但在AS3中,一个类只能继承一个抽象类。相比之下,一个类可以实现多个接口,这使得接口成为了一种更为灵活的选择。此外,接口还允许我们更自然地实现多态性,从而提高了代码的...

    AS3类继承树+AS3中文API

    另一方面,FlashCS3Help_cn.chm文件可能是一个包含Flash CS3版本的AS3中文帮助文档的CHM(Compiled HTML Help)文件,内含丰富的教程、示例和API参考,方便开发者查阅。 掌握AS3类继承树和中文API对于提升AS3编程...

    AS3中文版帮助文档

    这个“AS3中文版帮助文档”对于正在学习或从事AS3编程的开发者来说,无疑是一份非常宝贵的资源。 ActionScript 3.0相较于之前的版本,进行了重大更新和改进,包括更强的类型检查、更快的执行速度、更严格的语法,...

    Flash AS3 中文帮助文档

    2. **面向对象编程**:AS3支持类、接口、包、继承、多态和封装等面向对象特性。开发者可以创建自定义类,实现特定功能,例如继承DisplayObject类来创建自定义显示对象。 3. **事件处理**:AS3引入了事件驱动模型,...

    as3中文学习文档

    例如,可以尝试开发一个简单的游戏、动画或其他交互式应用程序,将理论知识应用于实践中。 综上所述,AS3作为一款功能强大且灵活的编程语言,在Flash Player和AIR平台上有着广泛的应用。通过深入学习上述知识点,...

    flash as3贪吃蛇

    6. **游戏循环**:贪吃蛇游戏需要一个主循环来不断更新游戏状态,处理用户输入,并渲染新的帧。这通常由 ENTER_FRAME 事件驱动。 7. **动画原理**:在AS3中,通过改变DisplayObject的位置或透明度来实现动画效果。...

    23种设计模式实例及说明大全(as3语言描述)

    3. 抽象工厂模式(Abstract Factory):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。在AS3中,可以使用接口和类组合实现。 4. 建造者模式(Builder):将一个复杂对象的构建与它的表示...

    Flash ActionScript3 AS3 23种设计模式(全).Design Pattern

    - 适配器模式:将一个类的接口转换成客户希望的另一个接口。 - 组合模式(已提及):在创建型模式中也提到,它属于结构型模式。 - 装饰模式:动态地给一个对象添加一些额外的职责。 - 复用模式(享元模式):...

    .netcore6 的Autofac使用实例 接口多个实例 ResolveByKey作用域

    这样可以确保在同一作用域内的所有组件共享同一个实例,而不同作用域之间的组件则拥有独立的实例。 在 `Startup.cs` 文件中,你需要配置 Autofac 作为应用程序的服务提供者。这通常包括调用 `services.AddAutofac()...

    AS3经典游戏范例之贪吃蛇游戏 .rar

    《AS3经典游戏范例之贪吃蛇游戏》是一个基于ActionScript 3(AS3)开发的Flash游戏项目,展示了如何使用AS3编程语言来创建一个互动性极强的贪吃蛇游戏。AS3是Adobe Flash Platform的核心语言,用于创建富互联网应用...

    as3游戏技能冷却特效

    AS3中的EventDispatcher接口允许对象监听和响应事件。在技能冷却过程中,可以触发自定义事件,如“COOLDOWN_START”和“COOLDOWN_END”,用于通知游戏逻辑和其他组件当前技能的状态。 5. **状态管理** 技能应有...

    设计模式之单例模式(AS3实现)

    单例模式是软件设计模式中的一种...总结来说,单例模式在AS3中的实现并不复杂,但其设计理念对于优化资源管理和提高代码复用性有着重要作用。了解和熟练运用单例模式,可以帮助开发者编写出更高效、更易于维护的代码。

    基于RTL8019AS的串口与以太网接口转换器

    《基于RTL8019AS的串口与...总的来说,基于RTL8019AS的串口与以太网接口转换器巧妙地实现了串行通信与以太网通信的无缝对接,是单片机系统融入互联网世界的关键桥梁,对于推动嵌入式网络系统的发展起到了重要作用。

    AS3简体中文帮助文档

    AS3简体中文帮助文档是一份专为AS3开发者准备的详尽指南,涵盖了AS3的基本语法、类库、事件处理、错误处理、性能优化等多个方面,旨在帮助开发者更好地理解和运用AS3进行编程。 在AS3中,一些关键知识点包括: 1. ...

    AS3 中的package(包)应用-代码

    在AS3中,我们通常将相关的类、接口和其他编程元素放入同一个包中,以便在不同的项目或库之间重用和导入。下面,我们将深入探讨 `package` 的用法及其在实际开发中的应用。 1. **包的定义与创建** - 在AS3中,`...

    纯as3写的打砖块游戏。简单。

    本文将深入探讨一个基于AS3编写的简单打砖块游戏,它没有使用hitTestObject API进行碰撞检测,而是采用了一种不同的策略。 首先,我们要了解AS3的基本语法和特性。AS3是一种面向对象的语言,具有强类型、高性能的...

    可做鼠标跟随切水果,连连看亮光效果AS3源码.rar

    在IT行业中,ActionScript 3(AS3)是一种强大的编程语言,主要应用于Adobe Flash平台,...AS3虽然现在已不再主流,但它在过去的互联网发展中起到了重要作用,对于理解现代Web交互设计和技术的发展历程仍然具有价值。

    as3 source code

    3. 继承:AS3允许一个类(子类)继承另一个类(父类)的特性。子类可以扩展或修改父类的行为,从而实现代码复用。`extends`关键字用于声明继承关系。 4. 多态:多态是指同一种操作可以作用于不同的对象,产生不同的...

    AS2toAS3.pdf

    此外,AS3 还支持内部类,即可以在同一个文件内定义多个类,这些类之间的访问关系更为紧密。 **转换建议**: - 直接将 AS2 的类迁移到 AS3 时,通常无需做太多修改。 - 使用 `internal` 来限制类的可见性,有助于...

Global site tag (gtag.js) - Google Analytics