AS3 的一些用法

as3用了这么久,还没有仔细的看看细节,所以做了这么几个测试

  1. /**
  2. * as3类测试文件1
  3. * @author 湘西悍匪
  4. * @version 0.1
  5. */
  6.  
  7. package test{
  8.  
  9. public class Test {
  10. private static var a:String;
  11. /**
  12. * 以下的程序块在as3之中,被看作一个匿名的static函数
  13. * 和java的块相同的是,as3里的块语句执行的顺序是和java一样的,先于构造函数执行
  14. * 和java的块不同的是,java的块不是被看作static的
  15. * failed code:
  16. * private var a:String;
  17. * {
  18. * a = "hello";
  19. * trace(a);
  20. * }
  21. * throw:Access of undefined property a.
  22. * 以上代码会抛出错误,因为成员变量a不是static的,所以在这个块中将无法访问
  23. */
  24. {
  25. a = "hello";
  26. trace(a);
  27. }
  28. public function Test(){
  29. trace("in construct:"+a);
  30. }
  31. }
  32.  
  33. }
  1. /**
  2. * as3类测试文件2
  3. * @author 湘西悍匪
  4. * @version 0.1
  5. */
  6.  
  7. package test {
  8. /**
  9. * 在as3中,private ,portected关键字只能用于类成员的定义,不能在package里使用这两个关键字
  10. * package里只能有1个显示定义(public ,internal都算显式定义)
  11. * failed code:
  12. * package{
  13. * public class Test2{
  14. * }
  15. * class A{
  16. * }
  17. * }
  18. * throw:An ActionScript file can not have more than one externally visible definition: Test2,A
  19. * 以上代码抛出一个异常,ActionScript文件里只能有1个显式定义
  20. *
  21. * 在as3中,如果没有使用public关键字来标注一个class为公共的
  22. * 则这个class默认为internal的
  23. * failed code:
  24. * package{
  25. * class Test2{
  26. * public function Test2(){
  27. * trace("ok");
  28. * }
  29. * }
  30. * }
  31. * thorw:Type was not found or was not a compile-time constant: Test2.
  32. * 以上代码会抛出一个异常,该类型在编译时未能被找到,也就是说,没有用public
  33. * 来标注这个class,这个class是internal的,internal指的是仅仅能在内部被访问
  34. */
  35. public class Test2 {
  36. public function put():void {
  37. trace(new A().value);
  38. trace(new B().value);
  39. trace("A.getValueFromB:"+new A().getValueFromB());
  40. trace(n);
  41. }
  42. }
  43. }
  44.  
  45. /**
  46. *同样的,internal 方法和变量都遵循这个原则
  47. * 若果要任何内部成员可访问这些internal的属性和方法则这些属性和方法必须要放在包外,并且不再任何内类之中
  48. * 这样任何内部的类,都可以访问到这些internal的方法和变量。
  49. * 如果是在类的内部使用了internal关键字,则这个属性或方法,仅在这个类的内部可被访问.且不能被其他的internal class 访问
  50. */
  51. internal function t():void{
  52. trace("_________");
  53. }
  54. internal var n:Number = 5;
  55.  
  56. /**
  57. * as3中一个package里只能定义个class,其他的class定义要放在package以外
  58. * public关键字限定的class只能放在package内,也就是说,需要给外部可使用的class放在package里
  59. * 而其他辅助的internal class,则放在package外,给外部访问的class需要用public关键字来标记
  60. * failed code:
  61. * package{
  62. * class Test{
  63. * }
  64. * }
  65. * public class A{
  66. * }
  67. * throw: The public attribute can only be used inside a package.
  68. * 以上代码抛出一个异常,public 关键字 只能在package里使用
  69. */
  70. internal class A {
  71. public var value:String ="a";
  72. /**
  73. * 这里可以看到,internal class在内部环境里是可以访问的到的
  74. * class A可以访问到class B
  75. * 如果是在外部(例如在fla里的帧上写代码,试图创建一个B的实例),则会抛出错误
  76. */
  77. public function getValueFromB():String{
  78. t();
  79. return new B().value;
  80. }
  81. }
  82. internal class B {
  83. public var value:String = "b";
  84. }
  1. /**
  2. * as3类测试文件3
  3. * @author 湘西悍匪
  4. * @version 0.1
  5. */
  6.  
  7. package test{
  8.  
  9. ///
  10. // 在as3中,只有public 关键字限定的类,方法,属性才能被外部访问
  11. // 其他如private ,portected,internal等关键字限定的东西,都不可以被外部访问
  12. // private ,portected,internal在类的内部都是可以访问的,没有限制
  13. //
  14. public class Test3 {
  15. private var a:String;
  16. public var b:String;
  17. protected var c:String;
  18. internal var d:String;
  19. public function Test3(){
  20. a = "a";
  21. b = "b";
  22. c = "c";
  23. d = "d";
  24. }
  25. public function traceAll():void{
  26. trace(a);
  27. trace(b);
  28. trace(c);
  29. trace(d);
  30. }
  31. }
  32.  
  33. }
  1. /**
  2. * as3类测试文件4
  3. * @author 湘西悍匪
  4. * @version 0.1
  5. */
  6.  
  7. package test{
  8. /**
  9. * 在as3中,public class的编译顺序早于interval class
  10. * 通过以下代码可以测试到:
  11. * package{
  12. * public class A{
  13. * {
  14. * trace(”A was initialize”);
  15. * }
  16. * }
  17. * }
  18. * internal class B{
  19. * {
  20. * trace(”B was initialize”);
  21. * }
  22. * }
  23. * 以上代码运行结果为:
  24. * A was initialize
  25. * B was initialize
  26. *
  27. * 所以,不能将一个public class 的基类设置成一个internal class
  28. * failed code:
  29. * package{
  30. * public class A extends B{
  31. * }
  32. * }
  33. * internal class B{}
  34. * throw:Forward reference to base class B.
  35. * 以上代码抛出一个异常,因为A比B的编译顺序要早,在A被加载开始初始化的时候,B还没有加载
  36. */
  37. public class Test4 {
  38. public function Test4(){
  39. new B().traceAll();
  40. }
  41. }
  42.  
  43. }
  44. internal class A {
  45. private var a:String;
  46. public var b:String;
  47. protected var c:String;
  48. internal var d:String;
  49. public function A(){
  50. trace(im running!”);
  51. a = “a”;
  52. b = “b”;
  53. c = “c”;
  54. d = “d”;
  55. }
  56. private function f1():void{
  57. trace(f1);
  58. }
  59. public function f2():void{
  60. trace(f2);
  61. }
  62. protected function f3():void{
  63. trace(f3);
  64. }
  65. internal function f4():void{
  66. trace(f4);
  67. }
  68. }
  69. internal class B extends A{
  70. public function traceAll():void{
  71. /**
  72. * private限定符表示严格的私有只能在当前类可以访问,而子类不能访问
  73. * public限定符表示完全公开,当前类,子类,外部都可以访问
  74. * protected限定符表示友好的,当前类,子类,可访问,但外部不能访问
  75. * internal限定符表示内部友好,当前类,子类,可访问,外部不能访问
  76. */
  77. //trace(this.a);
  78. trace(this.b);
  79. trace(this.c);
  80. trace(this.d);
  81. /**
  82. * 对于和父类重名的方法,as3规定,必须使用override关键字标明重载
  83. * 这和java有点不一样,因为as3中没有多态。对于同方法名,不同参数和不同返回值的方法,as3会认为是定义重复
  84. * private 标记的方法不会从父类继承下来,所以这里的f1不需要重载
  85. * public,protected,internal这些关键字定义的方法,如果在子类里有重名,是必须要重载的
  86. * as3里的重载和java是不一样的,必须严格的按照父类的方法定义进行重载
  87. * java里允许子类对父类方法重载而且可以改变访问限制,如public 的可以在子类里变成private的
  88. * java的规则是从宽松的访问方式到严格的可以,反之则不行,例如将private的变成public,这将抛出异常
  89. * as3里父类的方法限定符号是什么,子类也必须使用这个限定符号,并且参数,返回值也必须是一致的
  90. * 从外观上来看,父类方法和子类方法的区别在于子类多出了一个override关键字
  91. * 方法被重载以后,可以通过super关键字访问到父类的原始方法,如:super.f2();
  92. * 在被重载的方法里这个super关键字对位置没有要求,不必放在第1行,可以根据需求来改变
  93. */
  94. f1();
  95. f2();
  96. f3();
  97. f4();
  98. }
  99.  
  100. private function f1():void{
  101. trace(b.f1);
  102. }
  103. public override function f2():void{
  104. super.f2();
  105. trace(b.f2);
  106. }
  107. protected override function f3():void{
  108. trace(b.f3);
  109. }
  110. internal override function f4():void{
  111. trace(b.f4);
  112. }
  113. }
  1. /**
  2. * as3类测试文件5
  3. * @author 湘西悍匪
  4. * @version 0.1
  5. */
  6.  
  7. package test{
  8. /**
  9. * 根据as3里,actionscript文件package里只能有1个显示定义的原则。
  10. * 如象flash.utils.trace这样的包方法,需要单独编写一个as文件
  11. * 因为要被外部使用,所以方法的限定符号为public
  12. * 文件名要和function名字存成一样
  13. */
  14. public function myTrace(v:*):void{
  15. trace(v);
  16. }
  17. }

以上仅仅自己测试得出的结论,如有错误,请告之我,谢谢

名片设计

Aug 15

在AS3中使用嵌入字体

在flash中,我们常会遇到需要嵌入字体的情况,在以往的flash版本中,嵌入字体相信是大家已经耳熟能详的事情了,这里我要写的是在as3中如何嵌入字体,以及在as3中嵌入字体所要注意的一些问题。

首先我们先制作一个嵌入字体资源文件,先新建一个fla,打开库,在库中新建一个字体,选择你想要嵌入的字体,我这里选的是“方正黄草简体”1.jpg

然后选中这个字体,对它的linkage进行设置

2.jpg

最后保存并发布为swf,这样我们的嵌入字体资源文件就制作完成了,现在我们来看看如何使用这个嵌入字体,新建一个fla,在第一帧写上如下代码:

  1. //新建一个loader
  2. var loader:Loader = new Loader();
  3. //设置applicationDomain
  4. var context:LoaderContext = new LoaderContext();
  5. context.applicationDomain = ApplicationDomain.currentDomain;
  6. loader.contentLoaderInfo.addEventListener(Event.COMPLETE,complete);
  7. loader.load(new URLRequest("fontLib.swf"),context);
  8.  
  9. function complete(e:Event) {
  10. //获取到嵌入的字体
  11. var f:Class = loader.contentLoaderInfo.applicationDomain.getDefinition("Font1") as Class;
  12. //注册字体
  13. Font.registerFont(f);
  14. var tf:TextFormat = new TextFormat();
  15. tf.font = "方正黄草简体";
  16. tf.size = 24;
  17. var txt:TextField = new TextField();
  18. //使用嵌入字体
  19. txt.embedFonts=true;
  20. txt.text="嵌入字体!";
  21. txt.setTextFormat(tf);
  22. addChild(txt);
  23. }

关于Loader的用法,可以查看帮助,而ApplicationDomain的具体信息,你可以去看下eidiot的这篇教程,而这里我们主要是了解Font,这是as3中使用嵌入字体的关键,Font.registerFont方法能注册一个字体到全局字体列表中,Font.enumerateFonts()方法可以返回一个当前嵌入字体的列表,你可以通过查看这个列表来看你的字体是否注册成功,这个方法有一个布尔值的参数,true为包含设备字体,flase为仅显示嵌入的字体,另外值得注意的是as3中使用嵌入字体,必须将文本的embedFonts设置为true,否则无法正常显示。
以上就是as3嵌入字体的全部了,如有遗漏或疑问,欢迎你前来讨论。

Aug 14

Doomsday_世界之窗2.0skin

最近为世界之窗浏览器做的skin Doomsday,希望朋友们喜欢^________^

doomsday.rar

Aug 12

Nantbuilder logo设计

最近为Nantbuilder的logo设计

Aug 8

as3与后台通讯

目前flash在各方个面的应用越来越广,而flash也不单只是注重自身绚丽的效果,也需要和外界程序交换数据,以实现更强大的功能,随着as3的到来,flash和外部交互的方式也越来越简便和合理化。今天就在这里谈谈as3和后台数据的交互(这里选择as3+php架构,其他配置同理)。

在as3里,原来的loadVars方法已经被废弃,而改用一系列的类来实现与后台数据的交互,这些类是:URLLoader,URLLoaderDataFormat,URLStream,URLVariables。
URLLoader 类和原来的loadVars类似,是加载文本,2进制数据,xml,URL数据等信息的有力工具。URLLoader接受一个URLRequest 作为构造的参数,使用load方法来加载数据。URLLoder也可以进行监听,这点也loadVars不同,一个简单的示例如下:

  1. //actionscript code//
  2. //声明一个URLLoader
  3. var loader:URLLoader = new URLLoader();
  4. //监听数载加载完成事件
  5. loader.addEventListener(Event.COMPLETE,loaded);
  6. //事件相应函数
  7. function loaded(e:Event){
  8. trace(loader.data);
  9. // output : this data is from php!
  10. }
  11. //加载test.php
  12. loader.load(new URLRequest("test.php"));
  1. // test.php code/
  2. <?php
  3. //声明一个变量并赋给一个字符串
  4. $data ='this data is form php!';
  5. //输出这个变量给flash
  6. echo $data;
  7. ?>

从上面的示例可以看出,as3和后台交互是多么简单,但这只是单项的交互,如果要flash向后台发送数据并传回数据该如何去做呢?这个时候你可能会把代码该成这样:

  1. //actionscript code
  2. var loader:URLLoader = new URLLoader();
  3. loader.data={message:"hello im flash!"};
  4. loader.addEventListener(Event.COMPLETE,loaded);
  5. function loaded(e:Event){
  6. trace(loader.data);
  7. // output : this is flash say:
  8. }
  9. loader.load(new URLRequest("test.php"));
  1. //test.php code//
  2. <?php
  3. $flashData = $_POST['message'];
  4. echo "this is flash say:$flashData";
  5. ?>

看看输出的代码,你得到了什么?是的,信息并没有传输到php,你还是在用loadVars的方式试图传送数据,但as3里已经不是这样了,URLLoader的data只有在数据被下载完时才会被初始化,在数据没有加载完成时,它是等于null的,也就是说,它只包含接受到的数据,而不管要发送的数据,那么,as3里如何向后台发送数据呢?使用URLVariables。URLVariables允许你在flash和后台程序间传输变量,as3里已经把发送和接受数据分离,再也不像as2的loadVars那样,一个类通吃所有了,那么这个URLVariables如何送要发送的数据呢?
你可能找遍了URLLoader的文档也没有发现与它相关的东西,是的URLLoader并不和URLVariables有关联,而是URLRequest在使用它,URLRequest包含整个http请求的所有信息,所以我们要发送的数据要放在这里,URLRequest有一个data属性他接受一个object类型的参数,这就是我们要发送的数据。同时你可能还注意到了,URLRequest也管理用什么样的方式来发送http请求,它的method属性接受一个字符参数,post或者是get。好了,现在我们来看看它们是怎么工作的:

  1. //actionscript code
  2. var loader:URLLoader = new URLLoader();
  3. //声明一个URLRequest
  4. var url:URLRequest = new URLRequest("test.php");
  5. //设置传输方式为POST
  6. url.method = URLRequestMethod.POST;
  7. //声明一个URLVariables
  8. var values:URLVariables = new URLVariables();
  9. //设置要传输的信息
  10. values.message="hello im flash!";
  11. url.data = values;
  12. loader.addEventListener(Event.COMPLETE,loaded);
  13. function loaded(e:Event){
  14. trace(loader.data);
  15. // output : this is flash say:hello im flash!
  16. }
  17. loader.load(url);
  1. //test.php code//
  2. <?php
  3. $flashData = $_POST['message'];
  4. echo "this is flash say:$flashData";
  5. ?>

怎么样,是不是也很方便的实现了as3和后台的数据传输?恩,现在我们的程序可以双向交互数据了,但这只是一些简单的数据,如果你要传输带有结构的数据,(熟悉as2的人都知道loadVars可以自动解析下载数据的结构),让我们先按loadVars的方式来尝试下,看看URLLoader是不是能自动的解析下载的数据。

  1. //actionscript code
  2. var loader:URLLoader = new URLLoader();
  3. //声明一个URLRequest
  4. var url:URLRequest = new URLRequest("test.php");
  5. //设置传输方式为POST
  6. url.method = URLRequestMethod.POST;
  7. //声明一个URLVariables
  8. var values:URLVariables = new URLVariables();
  9. //设置要传输的信息
  10. values.message="hello im flash!";
  11. url.data = values;
  12. loader.addEventListener(Event.COMPLETE,loaded);
  13. function loaded(e:Event){
  14. trace(loader.data);
  15. //outPut: phpMessage=im php message!&flashMessage=hello im flash!
  16. trace(loader.data.phpMessage);
  17. // thorw Error;
  18. trace(loader.data.flashMessage);
  19. // thorw Error;
  20. }
  21. loader.load(url);
  1. //test.php code//
  2. <?php
  3. $flashData = $_POST['message'];
  4. $phpMessage = 'im php message!';
  5. echo "phpMessage=$phpMessage&flashMessage=$flashData";
  6. ?>

可以看到,数据被完全下载下来了,但是却没有被解析,还抛出了异常,那么是不是URLLoader就不能自动解析数据了呢?不是,相反URLLoader提供了多种数据解析方式供你选择。这些数据解析方式都在URLLoaderDataFormat里,他们是:BINARY-以2进制的方式解析 TEXT-以文本的方式解析 VARIABLES-以变量-值配对的方式解析。URLLoader的dataFormat属性提供了对解析方式的选择,好,我们再来修改下程序使它变的更完美些:

  1. //actionscript code
  2. var loader:URLLoader = new URLLoader();
  3. //声明一个URLRequest
  4. var url:URLRequest = new URLRequest("test.php");
  5. //设置传输方式为POST
  6. url.method = URLRequestMethod.POST;
  7. //声明一个URLVariables
  8. var values:URLVariables = new URLVariables();
  9. //设置要传输的信息
  10. values.message="hello im flash!";
  11. url.data = values;
  12. //设置以变量-值配对的方式解析数据
  13. loader.dataFormat = URLLoaderDataFormat.VARIABLES;
  14. loader.addEventListener(Event.COMPLETE,loaded);
  15. function loaded(e:Event){
  16. trace(loader.data);
  17. //outPut: phpMessage=im php message!&flashMessage=hello im flash!
  18. trace(loader.data.phpMessage);
  19. // im php message!
  20. trace(loader.data.flashMessage);
  21. // hello im flash!
  22. }
  23. loader.load(url);
  1. //test.php code//
  2. <?php
  3. $flashData = $_POST['message'];
  4. $phpMessage = 'im php message!';
  5. echo "phpMessage=$phpMessage&flashMessage=$flashData";
  6. ?>

以上这些就是as3里和后台交互的基础内容,现在你可以在as3里创建这样的交互,获取动态数据来丰富你的程序,在你开始自己动手实验之前,还有一些东西值得注意:
1,记得捕获和处理异常(上述的例子里都是假定在完美的测试环境下运行,所以没有加上异常捕获和处理的代码,但现实中你可能会遇到各种各样的情况)URLLoader可能引发好几种异常情况(详细请参见说明文档)
你应该通过监听ioError和securityError事件,或者通过try-catch来处理他们,即使你确信不会发生这样的问题。
2,文件的编码,这是个常见的问题,经常很多数据变成了乱码,或者解析出错,都是因为编码的问题,我的做法是确保发送的数据和后台传回的数据都是UTF-8格式(因为flash默认编码为utf-8)
最后希望这篇文章能对你有所帮助,也欢迎你留言讨论相关的问题。

 
一个就是使用继承。比方说,你可以先创建一个颜色处理器的类。 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{ functon 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) or (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多个类的时候,或者再细分至省和洲的时候,这一做法的优势就更为明显了。 总结起来,可以得知,在类的继承结构不能仅用树状去表示,如上面的具有交叉继承结构的时候,就建议用接口了。但是,如果是简单的树状结构,我觉得还是用类继承好些,毕竟这样的做法也有维护上的优势。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值