AS30类的一般结构.docx
《AS30类的一般结构.docx》由会员分享,可在线阅读,更多相关《AS30类的一般结构.docx(22页珍藏版)》请在冰豆网上搜索。
AS30类的一般结构
类的一般结构
package{
publicclassMyClass{
类成员;
publicfunctionMyClass(){//构造函数
}
}
}
package表示包的意思,表示类文件保存的位置,文件名与类名相同。
建立为一个类后,我们就可以像flash提供的其它类一样,可在AS3.0代码中使用。
如下
varmy:
MyClass=newMyClass();
类的成员有成员常量、成员变量、成员函数三种:
如下的一个类
package{
publicclassMyClass{
publicconstpi:
Number=3.1415926;
publicvarr:
Number;
privatevars:
Number;
publicfunctionMyClass(){
}
}
}
其中pi为成员常量、r,s为成员变量、MyClass为成员函数。
public,private是属性关键字,表示成员的可见性。
public:
表示指定类、常量、变量、方法可用于任何调用者。
private:
表示常量、变量、方法仅供声明它或定义它的类使用。
protected:
表示常量、变量、方法或命名空间只用于定义它的类及该类的任何子类。
internal:
表示类、常量、变量、方法可用于同一包中的任何调用者。
请看下段代码
varm:
MyClass=newMyClass();
m.r=3;//正确
m.s=8;//错误
要在外部改变s或访问s要如何呢?
我们来修改一下MyClass如下
package{
publicclassMyClass{
publicconstpi:
Number=3.1415926;
publicvarr:
Number;
privatevars:
Number;
publicfunctionMyClass(){
}
publicfunctionsetSValue(value:
Number):
void{
s=value;
}
}
}
这样就有一个公共公共方法设置s的值,可以使用如下语句设置s的值。
m.setSValue(18);
与其它语言一样,我们可以使用get和set方法来读取与写入private变量的值。
package{
publicclassMyClass{
publicconstpi:
Number=3.1415926;
publicvarr:
Number;
privatevars:
Number;
publicfunctionMyClass(){
trace(‘这是MyClass的构造函数’);
}
publicfunctionsetsValue(value:
Number):
void{
s=value;
}
publicfunctiongetsValue():
Number{
returns;
}
}
}
我们在调用时可以使用如下语句
m.sValue=18;//当使用set方法后可以使用
vara:
Number=m.sValue;//当使用get方法后可以使用。
类的继承
继承是指一种代码重用的形式,允许程序员基于现有类开发新类。
现有类通常称为“基类”或“超类”,新类通常称为“子类”。
先看一段代码
package{
publcclassMySubClassextendsMyClass{
publicfunctionMySubClass(){
trace(‘这是MySubClass构造函数’);
trace(“pi:
”,pi);//正确
trace(“r:
”,r);//正确
trace(‘s:
’,s);//错误
}
}
}
可以看到pi,r,s是在MyClass这个类中定义的常量、变量,那么由于MySubClass继承了MyClass,所以MySubClass也能使用这些量,但代码前两个是正确,后一个是错误,这是什么意思呢,回忆下上一节学到的“属性关键字”。
public和protected在子类中是可以使用的,private是不行,所以这里pi和r可以使用的,s不能用,并且子类在构造的时候也会执行基类的构造方法。
观察如下语句(将错误语句删除)
varmySub:
MySubClass=newMySubClass();
输出为
这是MyClass构造函数
这是MySubClass的构造函数
pi:
3.1415926
r:
NaN
上节的继承是继承我们自己定义的类,如果要用到影片和类关联起来,我们可能会更多的去继承AS3.0中已有的类——Sprite的MovieClip;
package{
importflash.display.Sprite;
publicclassMySpriteextendsSprite{
publicfunctionMySprite(){
graphics.beginFill(0xFFCC00);
graphics.drawCircle(40,40,40);
}
}
}
现在我们建立一个MySprite的类,因为它是继承的Sprite类,所以我们可以使用graphics来画图,这里我们画一个圆。
要使用这个类,我们同样要在帧上加一些代码:
varmySprite:
MySprite=newMySprite();
addChild(mySprite);
mySprite.x=100;
mySprite.y=100;
文档类:
在FlashCs3.0中加入了一个文档类(documentclass)的概念,使用文档类后,我们刚才写帧上面的代码就不用了,直接写在文档类里面,文档类就相当于第一帧的位置,这样我们就不用在Fla文件里写代码了,所有代码都写在AS文件里达到了界面与代码的分离。
写一个文档类
package{
importflash.display.Sprite;
publicclassMainFormextendsSprite{
publicfunctionMainForm(){
varmySprite:
MySprite=newMySprite();
addChild(mySprite);
mySprite.x=100;
mySprite.y=100;
}
}
}
新建一个fla文档(ActionSprite3.0),保存的同一个目录下,设置文档属性中的文档类为MainForm。
加载库中的MC
上一节中,我们将库中的MC键接到一个类上,达到了类与元件的绑件,那么要完成像2.0一样的效果,将库中的元件载入到场景中是不是也要在MC上链接类了(3.0中没有以前的标识符),如果每个在库中的MC都要链接一个类就麻烦了,其它只需要在类后面起个名字就可以了。
比如我们起个名字叫MyMc基类就用默认的flash.display.MovieClip(注意在点确定时有个找不到类我警告,不用管它,点确定就可以了),在文档类中这样写:
package{
importflash.display.Sprite;
publicclassMainForm1extendsSprite{
publicfunctionMainForm1(){
varmymc:
MyMc=newMyMc();
addChild(mymc);
varmysound:
MySound=newMySound();
mysound.play();
}
}
}
同样,要播放库中的声音也可以这样做,链接的类后面取一个名字MySound,基类MySound,基类就用默认的flash.media.Sound
反射的方式加载库里的MC
在上一节中我们用到了在库中加载一个元件,我们还有另一个方法来加载一个元件,就是用“反射”的方法,反射就是用库中元件的名字(字符串)去得到我们想要的元件,用代码去把它变成一个类。
我们在库中建立两个MC,并用上一节的方法将它们导出,名字分别为Mc1和Mc2,我们要将这两元件加载到场景上,按照上一节的方法,我们应该这样做:
package{
importflash.display.Sprite;
publicclassMainForm2extendsSprite{
publicfunctionMainForm1(){
varmc1:
MovieClip=newMc1();
addChild(mc1);
varmc2:
MovieClip=newMc2();
addChild(mc2);
}
}
}
那么如果用反射的方法应该怎样做呢,看下面的代码
package{
importflash.display.Sprite;
importflash.display.MovieClip;
importflash.utils.getDefinitionByName;
publicclassMainForm3extendsSprite{
publicfunctionMainForm3(){
varClassReference:
Class=getDefinitionByName("Mc1")asClass;
varinstance:
MovieClip=newClassReference();
addChild(instance);
}
}
}
这段代码只加载了Mc1这个元件,而且我们发现代码比上一种方法更复杂一些,那为什么要使用反射这种方法呢,我们在看一段代码:
package{
importflash.display.Sprite;
importflash.display.MovieClip;
importflash.utils.getDefinitionByName;
publicclassMainForm4extendsSprite{
publicfunctionMainForm4(){
for(vari:
int=1;i<=2;i++){
varClassReference:
Class=getDefinitionByName("Mc"+i)asClass;
varinstance:
MovieClip=newClassReference();
instance.x=Math.random()*stage.stageWidth;
instance.y=Math.random()*stage.stageHeight;
addChild(instance);
}
}
}
}
我们发现现在这种方法是不是更简单的一种写法,当库中有名字为Mc1,Mc2,Mc3……这种更多的MC时,我们只需要改变循环变量的范围就可以了。
事件
在As3.0中我们用的最多的可能就是“事件”,我们会侦听各种事件。
在3.0中我们一律用addEventListener这种加侦听的方式来完成。
Btn.addEvetnListener(MouseEvent.CLICK,btnClickHandler);
FunctionbtnClickHandler(event:
MouseEvent):
void{
//点击后执行的代码
}
我们将上一节代码稍加修改,如下
package{
importflash.display.Sprite;
importflash.display.MovieClip;
importflash.utils.getDefinitionByName;
importflash.events.MouseEvent;
publicclassMainForm5extendsSprite{
publicfunctionMainForm5(){
for(vari:
int=1;i<=2;i++){
varClassReference:
Class=getDefinitionByName("Mc"+i)asClass;
varinstance:
MovieClip=newClassReference();
instance.x=Math.random()*stage.stageWidth;
instance.y=Math.random()*stage.stageHeight;
instance.name="Mc"+i.toString();
addChild(instance);
instance.addEventListener(MouseEvent.CLICK,insClickHandle);
}
}
privatefunctioninsClickHandle(e:
MouseEvent):
void{
trace(e.target.name);
}
}
}
事件侦听
在上一节我们介绍了侦听,要知道我们可能经常会用到侦听,所以我们会写很多个addEventListener经常有引起侦听我们用过一次后可以就不会再用了,那么为了节省资源,我们要将这些侦听删除掉,要删除侦听它们用这样的方法
instance.addEventListener(MouseEvent.CLICK,insClickHandler);//添加侦听
instance.removeEventListener(MouseEvent.CLICK,insClickHandler;//删除侦听
这里我们用removeEventListener就可以将侦听删除,我们在编程中,已经不用的侦听我们应该及时删除以节省资源。
现在我们来看一个小例子,这个例子的功能是有两个按钮,点击其中一个自己变成不可点击,另一个可点击状态。
package{
importflash.display.Sprite;
importflash.display.SimpleButton;
importflash.events.MouseEvent;
publicclassMainForm6extendsSprite{
publicfunctionMainForm6(){
btn1.addEventListener(MouseEvent.CLICK,btnClickHandler);
}
privatefunctionbtnClickHandler(e:
MouseEvent):
void{
trace("你点击了:
",e.currentTarget.name);
btn1.addEventListener(MouseEvent.CLICK,btnClickHandler);
btn2.addEventListener(MouseEvent.CLICK,btnClickHandler);
e.currentTarget.removeEventListener(MouseEvent.CLICK,btnClickHandler);
}
}
}
消息机制
在MyClass中我们用到一个方法dispatchEvent,这个方法是用来发消息的,是不是只要写个类就可以用到dispatchEvent这个方法了,不是的,如果我们写的这个类不是继承Sprite是不能用的,凡是从EventDispatcher继承下来的类就可以使用这个方法。
我们在文档类中有一个这样的语句:
myClass.addEventListerner(Event.CLOSE,closeHandler);
因为在MyClass中dispatchEvent(newEvent(Event.CLOSE));发了一个Event.CLOSE事件,而在文档类中侦听了这个事件,所以就收到了这个消息。
说简单点就是一个要用dispatchEvent发消息,一个要用addEventListener侦听这个消息就可以了,这里我们用到了Flash的EVENT类里面自带的CLOSE事件,其它就是个字符串,我们也可以自己定义字符串,比如这样:
dispatchEvent(newEvent(“message”));
myClass.addEventListener(“message”,closeHandler);
事件传递参数
上一节中我们讲到了类与类之间的消息传递,其它是一个类发消息,另一个类侦听这个消息,我们在发消息的时候能不能传递参数呢,当然是可以的,其实发消息的时候传参数在2.0里面是很方便的,但3,0里面要去写一个类去继承Event这个类,感觉麻烦了许多,在我学习3.0初期一直不是很理解到了3.0为什么变复杂了,所以刚开始经常会用到扩展Event这个类,但到后来发现只要程序的架构写好了,这种方法是可有可无了,不过今天还是讲解这种方法的使用。
我们先写一个继承Event的类
package{
importflash.events.Event;
publicclassMyEventextendsEvent{
privatevar_object:
Object;
publicfunctionMyEvent(type:
String,object:
Object):
void{
super(type);
_object=object;
}
publicfunctiongetparam():
Object{
retrun_object;
}
}
}
这是一个简单的类,继承了Event类,在构造方法里有一个super(type),super的意思是执行父类的构造方法,也就是执行Event的构造,type是消息的类型,就是消息的名字,一个字符串,object就是我们要传递的参数要用到一个变量,是一个对象,下面是一个get方法,通过param这个名字去取_object这个对象的值。
再来看一下怎么用这个MyEvent类,修改上一节中的MyClass
package{
importflash.display.Sprite;
importflash.events.Event;
importflash.events.MouseEvent;
publicclassMyClassextendsSprite{
publicfunctionMyClass(){
addEventListener(MouseEvent.CLICK,clickHandler);
}
privatefunctionclickHandler(e:
MouseEvent):
void{
dispatchEvent(newMyEvent("myClassMessage",{a:
100,b:
200}));
}
}
}
我们发现修改代码并不多,由newEvent变成newMyEvent,也就是说以前的消息是自带的Event事件,现在发的是我们自己写的MyEvent事件,再看参数还有一个{a:
100,b:
200},这个参数就是我们传进去的对象,这个对象有两个属性值,一个叫a,值为100,一个叫b,值为200;
再来看文档类
package{
importflash.display.Sprite;
importflash.events.Event;
publicclassMainFormextendsSprite{
privatevarmyClass:
MyClass;
publicfunctionMainForm(){
myClass=newMyClass();
myClass.name='myClass';
addChild(myClass);
myClass.addEventListener("myClassMessage",closeHandler)
//myClass.addEventListener("message",closeHandler);
}
privatefunctioncloseHandler(event:
MyEvent):
void{
trace("你收到了"+event.currentTarget.toString()+"的消息");
trace(event.type);
trace(event.param.a,',',event.param.b);
trace(event.param.toString());
}
}
}
文档类中修改的地方是侦听到消息后执行的方法,我们发现参数的类型变成了MyEvent,因为我们发的是MyEvent的事件,这里收到事件的类型当然是MyEvent,在event.param就是去取MyEvent._objcet,就是我们在MyClass传过的对象了,eventparam.a的值为100,event.param.b的值就是200。
这样我们就达到了传递参数的目的了。
单例模式
在使用其它语言中,比如C++,JAVA,会用到一些设计模式,使程序结构更加合理化,今天我们来看一下设计模式中最基本的一种——单例模式。
讲单例模式之前我们先看一个普通的例子,先建一个普通的类:
package{
publicclassMySubClass{
publicvarnum:
Number=0;
publicfunctionMySubClass(){
}
}
}
下面再建两个类,这两个类都生成MySubClass的实例
package{
publicclassOneClass{
privatevarmySubClass:
MySubClass=newMySubClass();
publicfunctionOneClass(){
mySubClass.num=5;
}
}
}
package{
publicclassTwoClass{
privatevarmySubClass:
MySubClass=newMySubClass();
publicfunctionTwoClass(){
trace(mySubClass.num);//结果为0
}
}
}
在OneClass和TwoClass这两类中都有MySubClass的实例,如果我们改变其中一个实例,其它的是不会更改的,因为它们不是同一个实例,所以第一个把num改为5,第二个里面仍是0,它们间没有联系。
单例模式的意思是不管怎么样都只产生一个实例,我们现在来修改MySubClass的代码
package{
publicclassMySubClass{
privatestaticvarmySubClass:
MySubClass;
publicvarnum:
Number=0;
publicfunction