|
第二部分 面向对象编程 |
|
|
第五章
类和对象 |
|
|
统一建模语言 |
+helloString:String ;
+Hello();
+sayHello(); |
|
|
一个类就是一群对象所共有的结构和行为,而一个对象对外部公开的属性和方法被称为对外部的界面接口。 |
|
类的成员 |
类名称 包路径
构造函数
属性 实例属性 静态属性
方法 实例方法 静态方法 |
|
默认访问控制 |
类 和 类的成员的默认访问控制都是internal |
|
|
如果我们把构造函数的引用赋值给一个变量,那么使用new
加这个变量也可以创建该类的对象。 |
|
Class中各构成部分的排序 |
静态属性 静态方法 实例属性 构造函数
实例方法 |
|
访问控制类型 |
interna public private protect |
|
访问实例属性和实例方法的方法 |
.
[] |
|
静态 |
静态的属性和方法不依赖于实例而存在 |
|
静态的模式应用 |
在工厂模式,单例模式,享元模式 |
|
静态属性的声明 |
internal static var 属性名:属性类型
访问控制应该在static之前 |
|
静态属性和方法的应用 |
1 集中管理数据(这个我用过)
2 实现枚举类型 只包含具有不同状态的属性,P92页asw
public static const HIGH:EnumSample = new EnumSample();
EnumSample这个类是final的 ,可以避免类被继续而被改写
3 工具类
public static function
方法名(参数...args):返回值{};
|
|
构造函数 |
访问控制永远是public
|
|
动态类和密封类 |
类名前有dynamic就是动态类,没有就不是
动态的意思就是可以动态添加实例属性和方法 |
|
this |
1.只应用于实例属性和实例方法
2.使用的情况:a.向第三方提供自身的引用,b.与return结合,返回自身的引用.c.同名是,来明确使用的类的实例属性
3.同名属性的判断使用顺序是
局部变量->方法参数->实例属性->静态属性
|
|
方法重载 |
1.定义,即同名函数实现不同的功能
2.方法,a,方法的参数用..args . b,返回值写成*或Object
|
|
包外类 |
1.一个类文件中可以有多个类,甚至可以直接写入一次性执行的语句
2.package关键字后面的花括号内只能定义一个Class。且这个Class名必须与as文件同名
3.包外类可以定义多个,且只有当前类文件中的成员类可以访问 |
|
第六章 类的成员 类 包与访问控制 |
|
|
OOP的三大要素 |
封装 继承 多态 |
|
封装的内容 |
类的成员访问控制,类的访问控制,命名空间的使用 |
|
封装定义 |
encapulation
又叫隐藏实现,将具体的实现细节隐藏起来,只将必要的功能接口对外公开。
OOP编程中,对代码单元访问控制得越严格,日后修改代码的自由度越大 |
|
封装的层次 |
包外,包,类,包外类 |
|
全饰名称 |
fully qualified name
类名相当于类的小名,全饰名称才是类的大名。 |
|
import |
导入包是为了让编译器通过import语句准确找到我们要的类,这样,我们就不用使用冗长的全饰路径,直接使用类名即可 |
|
什么时候import |
使用任何一个类文件,必须先导入这个类文件所在的包,即使使用全饰路径,也必须先导入包。 |
|
Flash中的引入 |
在时间轴的关键帧中直接写入代码,那么flash.*下的类都会在编译时自动导入。而不需要在代码中写明;但如果是导入除了flash.*以外的包,那么仍需要import |
|
使用通配符导入整个包 |
不提倡 |
|
使用同一个包中的类文件无须导入 |
|
|
如果出现两个不同包中的类名相同的情况,如何使用 |
这种情况就要用到全饰名称 |
|
Flash CS3中如何设置类路径 |
ctrl+ u
.preferences->ActionScript
->ActionScript 3 Settings
->当前有两个默认的类路径。
一个是. 一个是系统类包的路径,包括flash.*
fl.* adobe.utils |
|
Flex 项目中的类路径 |
包括源路径 和 类库路径
源路径:分散在不同目录中的源代码文件夹
类库路径:第三方类库所在的文件夹。 |
|
public |
public的类成员应当看成是这个类对外部所做出的承诺,协议。日后不能轻易改动。不能仅仅为了其它类可以访问某个成员,而轻率地将该成员public. |
|
|
要尽量将类成员的访问权限控制到最低限度 |
|
private |
对于复杂数据类型的属性来说,private的封装只是说不能通过当前类的实例来访问,并不意味着这个属性持有的引用所指向的对象不能被访问。 |
|
getter setter |
1.目的,可以对私有属性访问控制,可以设置只读属性和只写属性
2.隐藏了类的实现细节
3.在getter和setter方法中可以插入额外的代码逻辑。
4.也不一定非要和某个属性联合使用
|
|
类的访问控制 |
只有两种 私有(包类访问)
公有(开放) 默认是internal |
|
包外类的用途 |
实现单例。
|
|
包外类的特点 |
对类外不可见性 和 在类内的优先性, |
|
|
|
|
第七章
命名空间namespaces
|
这章先不看呢t |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
第八章 复合与继承 |
|
|
1.复合和继承的核心思想 |
都是重用现有的代码 |
|
复合 |
直接在新类中创建现有的Class对象 |
|
复合类的访问控制 |
复合类和被复合类往往都在独立存在的类文件,在同一个包里。被复合类的对外类成员访问控制往往设为默认的internal,只对包内可见;而复合类对外接口往往是public的,这也是模块思想的一个体现 |
|
初始化复合对象的三个方法 |
1.定义属性时就初始化复合对象。当复合的对象占用资源大,比如位图对象,网络连接,或者需要在运行时创建复合对象的,这种方法不宜用。
2.在构造函数中。满足大多数情况的需求,建议单独写一个init开头的方法,符合编程惯例。
3.使用对象的时候。在占用资源大或者资源稀缺的时候,就会采用这种方法。 |
|
复合和聚合的区别 |
有三点。P150.
。最大的区别是。复合同生共死。聚合各安天命。
|
|
extends |
是用来声明继承的关键字,它不支持多继承。但可以通过实现接口达到类似多继承的效果。
|
|
符合继承的条件 |
1.新类拥有与原有类相同的对外接口(这个接口指的是,公开的属性和方法,通常所说的接口表示抽象类型)
2.使用原有类的地方都可以用新类来替代 |
|
重写 |
override protected function
init():void{}
可以重写不是private的方法,
包外的类能不能继承并重写当前类的internal的属性呢? |
|
继承的东西有哪些 |
非private的实例属性和实例方法。
|
|
静态成员的继承 |
1.类的静态成员不能被子类继承
2.但是子类可以访问父类的静态成员,不管是属性还是方法,父类的静态成员的范围链是父类和所有子类
3.如果子类中的实例成员名称或新定义的静态成员名称与父类静态成员名称相同,那么父类的静态成员将被遮蔽。
4.在某些情况下,一定要使用子类加上静态成员名称来访问。这时,可以用伪继承。即在子类中故意定义同名的静态成员,将父类的静态属性赋值给相应的子类静态属性。
static const foo:String = Bass.foo |
|
继承中的proteted |
父类中的protected类成员,在子类中可以被访问到。即使父类和子类并不在同一个package中,子类也一样可以访问父类的protected类成员。如果没有继承,那么protected的关键字的作用和private一样 |
|
重写override |
经常要改变继承自父类中的某个属性或方法中的内容,但不改变名称,从而达到子类同名方法实现不同功能的多态效果。 |
|
可以重写什么 |
1.非private 也非final的实例方法可以
2.实例属性不可以,其实是指实例属性的类型不能变,这是为了保证强制转换。如果只想改变父类实例属性的初始值,要以在构造中留一下init()方法,在子类中重写这个方法
P156
3.而静态成员因为不能被继承,如果要重写,可以在子类中定义同名成员。 |
|
如何重写 |
1.必须用override关键字在行首标明这是重写;子类中被重写的方法要和父类的方法有同样的访问控制,参数数目,参数类型,返回值类型。
2.重写的方法中的参数名称不必与父类中的相同。
|
|
继承与私有成员的关系 |
在子类中定义与父类同名的私有属性和私有方法时,只会看成这个新子类属性和方法,不需要override关键字来修饰。 |
|
继承与super |
super可以看成是一个变量,直接持有对父类的引用。而super就是父类的构造函数。 |
|
继承与final |
1.final
可以修饰类和类的方法。,不可以定义属性。
2.用final时,可以放在访问控制符前面,也可以放在访问控制符的后面。
3.为什么要使用final 。是从哪方面考虑的?P158 孙颖给出了漂亮的答案。 |
|
使用复合和继承的判断 |
1.要谨慎使用继承,绝不可随意使用
2.has-a是复合,is-a是继承
3.需要使用向上转换时,使用继承。 |
|
|
|
|
第9章 多态 |
|
|
1 .多态的定义 |
通过继承,一个类可以当成多种类来使用
1.当作自己本来的类
2.当作自己所有的父类类型
3.当成自己所实现的接口类型来使用 |
|
2.数据类型 |
狭义上,一个对象的数据类型就是它所属的类。
广义上,一个对象的数据类型包括它自己所属类,自己父类和所实现的接口类型。 |
|
3.EventDispatcher |
是AS3.0中最重要的的类之一,用于发送事件。这个类实现了flash.events.IEventDispatcher接口 |
|
4.as 和 is 的搭配 |
它俩一般搭配使用,先用is判断,如果为true再用as告知编译器将该对象理解成as数据类型 |
|
5.向上转换 |
把一个对象当成它的父类对象来使用
1.两种情况,如果一个方法需要的参数是父类对象,这时候我们可以直接传进去子类。
!!!!
2.把子类对象传给父类变量。。第一步是要把子类as 成父类。。。然后才能传给父类变量
!!!!!
|
|
6.里氏代换原则 |
Lisov Substitution Principle
LSP。在一个程序中,将所有类型为A的对象,都换成类型为B的对象,而程序的行为没有变化,那么类型B是类型A的子类型。 |
|
7.beginFill draw的使用 |
_shape.graphics.beginFill(color,Math.random);//颜色值,alpha值
draw(()
_shape.graphics.endFill(); |
|
8.向下转换 |
1.当一个子对象以父类数据类型使用时,可以将它再还原成子类对象。
2.在运行时,产生了很多父类类型的对象,要将它们识别为子类的对象,并加以不同的操作,这是向下转换的功能和威力所在 |
|
9.向下转换的两种方法及它的选择使用 |
1.两种方法分别是: 父类类型对象 as 子类类型;
子类构造函数(父类类型对象)//后一种叫做显示强制转换
2.
使用as,如果发现类型不合,这个as表达式返回的就是null;使用显示强行转换时,如果类型不合,那么就会抛出TypeError.类型不合时,使用
as,会因为返回值是null而执行失败;使用显示强制转换,则可以用异常处理机制来处理,尤其一些大型项目比较多用这种
3.总这,需要异常处理的,请使用显示强行转换;不需要的,请使用is和as关键字配合使用。
|
|
10.fill 和 move的配合 |
target.fill(0x669900);
target.move(posX,posY); |
|
|
|
|
第十章 抽象类和接口 |
|
|
1.抽象类 |
1.当一个父类不需要生成自己实例,只是用来继承是,这个类就是Abstract类。这样的父类会综合子类的一些行为,尽量将子类的共同的代码写入自身。在使用时作为子类对象的共同类型而存在,不需要生成它自己的实例。
|
|
2.抽象方法 |
不给出任何具体实现,完全是空的。由子类重写(override)出相关的具体实现。 |
|
3.AS3.0与抽象概念 |
1.AS3.0不提供abstract关键字,编译器也不支持抽象类的实现。
2.然而在AS3语言中存在着被系统支持的抽象类,比如flash.display.DisplayObject
和flash.display.DisplayObjectContainer就是真正的抽象类 |
|
4.如何应对没有抽象类 |
1.自己来实现抽象类,将抽象类都命名成Abstract开头,提醒自己不要实例化。
2.如果子类都在同一个模块里,请将父类的访问控制设为interanl,让它对包外不可见,降低外部实例化的风险。
3.如果父类和子类都要对外部可见,那么可以使用一些技巧实现真实的抽象类。一旦我们要将抽象类实例化时,会自动化抛出异常。
|
|
5.设计抽象类的原则 |
1.抽象类应拥有尽可能多的子类共同代码
2.抽象类中的数据能少则少
3.抽象类中定义的抽象方法都必须在子类中重写,不应忘记。???????? |
|
6.抽象类的实现原理
这个没有太懂???? |
1.
在抽象类的构造函数中插入一行代码。通过第三方工具类AbstractEnforcer判断当前生成的对象是否确实是是抽象类的类型,如果是则抛出
AbstractError异常对象。而判断的原理是先使用flash.utils.getQualifiedClassName()得到当前生成的对象
所属类的全饰名称,传入flash.utils.getDefinitionByName()
。得到生成这个对象所属类的Class对象的引用。然后用这个引用和抽象类的Class对象比较,如果一致则说明生成的是抽象实例,马上抛出异常。如果不
一致,那么生成的是子类实例,顺利通过。
抽象类实例化异常的消息是AbstractError.CONSTRUCTOR_ERROR.
|
|
7.抽象方法的实现原理 |
在抽象方法中插入一行代码,抛出AbstactError对象。如果子类不重写抽象类这个方法,而直接调用,那么就会触发这个异常,很简单,很实用。抽象方法被调用的异常类型是AbstractError.METHOD_ERROR. |
|
8.使用Mims Wright方法必须要用到下面的几个类和方法 |
com.mimswright.utils.AbstractEnforcer
com.mimswright.utils.strictIs()
com.mimswright.errors.AbstractError |
|
9.在实际中的写法 |
import
com.mimswright.utils.AbstractEnforcer;
public function AbstractFoo(){
AbstractEnforcer.enforceConstructor(this,AbstractFoo);
}
public function hello():void{
AbstractEnforcer.enforceMethod();
trace("...");
} |
|
10.纯粹的抽象类 |
有不少抽象类非常纯粹,除了定义一些方法的名称,参数和返回类型外,没有任何代码。在运用中作用权限于作为一种数据类型。但其实这样的抽象类是很有作用的,给予了子类最大的灵活性 |
|
11.接口三个方面 |
1.实际意义,仅包含了一组方法声明,没有具体的代码实现。
2.语法上,只定义数据类型的public方法的名称,参数和返回类型,不给出实现,其余一概不管。
3.在运用中,核心是: 能够以其他数据类型向上转型,是接口的核心。
|
|
12.OOP编程之依赖倒转原则 |
要做任何具体的代码实现,首先要依赖于抽象的实现。
Gang of Four也提出另一种表述,即根据接口编程,而不是根据实现来编程
在具体的代码中,数据类型要尽理使用接口和抽象类,而不要使用具体类。
|
|
13.创建接口 |
package 包路径{
访问控制 interface
接口名称{
function
方法名(参数:参数类型):返回类型;
static function
方法名(参数:参数类型):返回类型;
function get
方法名():返回类型;
function set
方法名(参数:参数类型):void
}
} |
|
14.定义接口时的注意事项 |
1.接口也有访问控制,默认为internal.包内可见。如果需要公开,要将访问控制设为public
2.定义接口要用的关键字是interface
3.接口中只定义方法,不定义属性。定义的方法包括实例方法,静态方法,getter和setter
4.所有定义的方法不可以加访问控制符,接口中定义的方法都是public
5.定义的方法没有任何实现,没有大括号,直接以分号结束。
6.接口名称都要用I开头。
|
|
15.接口的实现 |
1.一个类在定义时如果实现(implements)一个接口,其实是在做一个宣告,它将拥有这个接口定义的所有方法,可以把它当成这种接口的数据类型来使用。
2.一个类可以实现多个接口,多个接口之间用逗号隔开 。
3.对接口中的定义的方法只能用public访问控制
4.名称必须和接口中的定义的方法名称相同。参数的数目,类型及方法的返回类型必须和接口中的方法的定义相同。
5.参数的名称不必与接口中的方法相同。方法的参数默认值不必与接口中的相同。
6.接口可以继承自另一个接口。而且接口能实现多继承,可以继承多个接口。
7.接口及所有父接口中的方法定义不能冲突,即不能出现同名的方法。接口继承中没有override的机制 |
|
16.使用接口的好处 |
一旦可以作为接口数据类型使用,就可以充分体会多态带来的好处。简单地说,就是可以使用向上转换和向下转换了 |
|
17.接口的类型 |
1.多方法接口
2.单方法接口,即接口中只定义了一个方法。好处在于让外部只调用对象一个特定方法。
3. 标识接口,即接口定义中没有任何方法,全部是空的。当需要将方法完全不同的几个类看成一个类型时,就要用到标识接口。比如
flash.display.IBitmapDrawable
就是一个很重要的标识接口,实现了这个接口的类的对象就可以作为source参数传给BitmapData的draw()方法。Bitmapdata和
DisplayObject这个类的结构很不相同,但都需要被作为source参数传给draw()。于是对过IBitmapDrawable就把这两个
没有关联的类统一成了IBitmapdataDrawable类型。还有mx.core.IContainer
mx.core.IFlexAsset
|
|
18.抽象类和接口的区别 |
1.抽象类是类,接口不是类.
2.抽象类只能单继承,接口能让一个类实现多个接口
3.如果为已存在的具体类添加抽象类型,使用接口要比抽象类简单,稳健。 |
|
19.抽象类和接口的选用 |
1.如果只是单纯地给已有的具体类添加新的抽象类型,那么就优先考虑接口。
2.如果需要给已有的具体类和将要设计的具体类中共同代码集中管理,那么就优先使用抽象类。
3.接口不能提供具体的代码实现,所以不能将共同的代码集中到接口中。但是,即使是在这种情况下,新定义一个接口,将抽象类声明为实现这个接口也是一种很好的编程思维
|
|
20.抽象类和接口的结合使用 |
有一个很好的经验,使用接口来声明数据类型,再给这个接口配上一个抽象类。
好处是:
1.充分利用了抽象类对子类的影响。
首先,抽象类中对接口的实现是被所有子类继承的,子类不必要再一一实现接口规定的方法。
其实,对抽象类的修改,将自动影响到所有子类。子类的共同代码可以移到抽象类。
最后。一旦接口做了改动,只需要改动抽象类就可以让子类继续适用,而不需要像之前那样,一旦接口对方法的定义做了变动,所有实现接口的类都必须一一修改
2.
给系统的扩展性留了更大的余地。ActionScript3在接口和抽象类结合方面就有一个非常重要的应用:所有Flex组件的共同父类--抽象类
mx.core.UIComponent和这个抽象类实现的接口mx.core.IUIComponent.接口IUIComponent定义了适用于于
Flex组件架构的抽象类型,抽象类UIComponent实现了这个接口。只要实现了IUIComponent接口的具体类都可以被Flex组件架构接
纳,并作为组件来使用。如果一个具体类本身已经继承了第三方的类,但是又想被作为Flex的组件类而融入组件架构中,那就可以通过实现
IUIComponent达到这个目的。这样组件系统的扩展性就大大增强。事实上,针对Flash CS3的组件工具包Flex
Component Kit for Flash CS3 就利用了这一点。它的核心类UIMovieClip
就是通过实现IUIComponent,使普通的MovieClip被Flex当成组件来运用 |
|
21.默认适配器 |
这个模式就是抽象类和接口的结合。
在
很多情况下,需要让一个具体类来实现一个接口,但是又用不到接口规定的方法。那么只好在类中定义一些空方法来满足接口的要求。与其这样,还不如设计一个抽
象类来实现接口,让这个具体类来继承抽象类。这样,在抽象类中用空方法实现接口的规定,在具体类中就不必要了,这个模式具有以上所讲的优点,而且运用这个
模式可以使具体类的代码更加清晰可读,不会有空方法的代码堆放着。 |
|
|
|
|
|
|