2005年01月13日
 
 

作者:eCool

 
 

MD5算法研究

 
 
综述

  MD5的全称是message-digest algorithm 5(信息-摘要算法),在90年代初由mit laboratory for computer science和rsa data security inc的ronald l. rivest开发出来,经md2、md3和md4发展而来。它的作用是让大容量信息在用数字签名软件签署私人密匙前被”压缩”成一种保密的格式(就是把一个任意长度的字节串变换成一定长的大整数)。不管是md2、md4还是md5,它们都需要获得一个随机长度的信息并产生一个128位的信息摘要。虽然这些算法的结构或多或少有些相似,但md2的设计与md4和md5完全不同,那是因为md2是为8位机器做过设计优化的,而md4和md5却是面向32位的电脑。这三个算法的描述和c语言源代码在internet rfcs 1321中有详细的描述(http://www.ietf.org/rfc/rfc1321.txt),这是一份最权威的文档,由ronald l. rivest在1992年8月向ieft提交。

  rivest在1989年开发出md2算法。在这个算法中,首先对信息进行数据补位,使信息的字节长度是16的倍数。然后,以一个16位的检验和追加到信息末尾。并且根据这个新产生的信息计算出散列值。后来,rogier和chauvaud发现如果忽略了检验和将产生md2冲突。md2算法的加密后结果是唯一的–既没有重复。

  为了加强算法的安全性,rivest在1990年又开发出md4算法。md4算法同样需要填补信息以确保信息的字节长度加上448后能被512整除(信息字节长度mod 512 = 448)。然后,一个以64位二进制表示的信息的最初长度被添加进来。信息被处理成512位damg?rd/merkle迭代结构的区块,而且每个区块要通过三个不同步骤的处理。den boer和bosselaers以及其他人很快的发现了攻击md4版本中第一步和第三步的漏洞。dobbertin向大家演示了如何利用一部普通的个人电脑在几分钟内找到md4完整版本中的冲突(这个冲突实际上是一种漏洞,它将导致对不同的内容进行加密却可能得到相同的加密后结果)。毫无疑问,md4就此被淘汰掉了。

  尽管md4算法在安全上有个这么大的漏洞,但它对在其后才被开发出来的好几种信息安全加密算法的出现却有着不可忽视的引导作用。除了md5以外,其中比较有名的还有sha-1、ripe-md以及haval等。

  一年以后,即1991年,rivest开发出技术上更为趋近成熟的md5算法。它在md4的基础上增加了”安全-带子”(safety-belts)的概念。虽然md5比md4稍微慢一些,但却更为安全。这个算法很明显的由四个和md4设计有少许不同的步骤组成。在md5算法中,信息-摘要的大小和填充的必要条件与md4完全相同。den boer和bosselaers曾发现md5算法中的假冲突(pseudo-collisions),但除此之外就没有其他被发现的加密后结果了。

  van oorschot和wiener曾经考虑过一个在散列中暴力搜寻冲突的函数(brute-force hash function),而且他们猜测一个被设计专门用来搜索md5冲突的机器(这台机器在1994年的制造成本大约是一百万美元)可以平均每24天就找到一个冲突。但单从1991年到2001年这10年间,竟没有出现替代md5算法的md6或被叫做其他什么名字的新算法这一点,我们就可以看出这个瑕疵并没有太多的影响md5的安全性。上面所有这些都不足以成为md5的在实际应用中的问题。并且,由于md5算法的使用不需要支付任何版权费用的,所以在一般的情况下(非绝密应用领域。但即便是应用在绝密领域内,md5也不失为一种非常优秀的中间技术),md5怎么都应该算得上是非常安全的了。

  算法的应用

  md5的典型应用是对一段信息(message)产生信息摘要(message-digest),以防止被篡改。比如,在unix下有很多软件在下载的时候都有一个文件名相同,文件扩展名为.md5的文件,在这个文件中通常只有一行文本,大致结构如:

   md5 (tanajiya.tar.gz) = 0ca175b9c0f726a831d895e269332461

  这就是tanajiya.tar.gz文件的数字签名。md5将整个文件当作一个大文本信息,通过其不可逆的字符串变换算法,产生了这个唯一的md5信息摘要。如果在以后传播这个文件的过程中,无论文件的内容发生了任何形式的改变(包括人为修改或者下载过程中线路不稳定引起的传输错误等),只要你对这个文件重新计算md5时就会发现信息摘要不相同,由此可以确定你得到的只是一个不正确的文件。如果再有一个第三方的认证机构,用md5还可以防止文件作者的”抵赖”,这就是所谓的数字签名应用。

  md5还广泛用于加密和解密技术上。比如在unix系统中用户的密码就是以md5(或其它类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的密码计算成md5值,然后再去和保存在文件系统中的md5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这不但可以避免用户的密码被具有系统管理员权限的用户知道,而且还在一定程度上增加了密码被破解的难度。

  正是因为这个原因,现在被黑客使用最多的一种破译密码的方法就是一种被称为”跑字典”的方法。有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用md5程序计算出这些字典项的md5值,然后再用目标的md5值在这个字典中检索。我们假设密码的最大长度为8位字节(8 bytes),同时密码只能是字母和数字,共26+26+10=62个字符,排列组合出的字典的项数则是p(62,1)+p(62,2)….+p(62,8),那也已经是一个很天文的数字了,存储这个字典就需要tb级的磁盘阵列,而且这种方法还有一个前提,就是能获得目标账户的密码md5值的情况下才可以。这种加密技术被广泛的应用于unix系统中,这也是为什么unix系统比一般操作系统更为坚固一个重要原因。

  算法描述

  对md5算法简要的叙述可以为:md5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

  在md5算法中,首先需要对信息进行填充,使其字节长度对512求余的结果等于448。因此,信息的字节长度(bits length)将被扩展至n*512+448,即n*64+56个字节(bytes),n为一个正整数。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后,在在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理,现在的信息字节长度=n*512+448+64=(n+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。

  md5中有四个32位被称作链接变量(chaining variable)的整数参数,他们分别为:a=0×01234567,b=0×89abcdef,c=0xfedcba98,d=0×76543210。

  当设置好这四个链接变量后,就开始进入算法的四轮循环运算。循环的次数是信息中512位信息分组的数目。

  将上面四个链接变量复制到另外四个变量中:a到a,b到b,c到c,d到d。

  主循环有四轮(md4只有三轮),每轮循环都很相似。第一轮进行16次操作。每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向右环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一。
以一下是每次操作中用到的四个非线性函数(每轮一个)。

   f(x,y,z) =(x&y)|((~x)&z)
   g(x,y,z) =(x&z)|(y&(~z))
   h(x,y,z) =x^y^z
   i(x,y,z)=y^(x|(~z))

   (&是与,|是或,~是非,^是异或)

  这四个函数的说明:如果x、y和z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。
f是一个逐位运算的函数。即,如果x,那么y,否则z。函数h是逐位奇偶操作符。

  假设mj表示消息的第j个子分组(从0到15),
  << ff(a,b,c,d,mj,s,ti) 表示 a=b+((a+(f(b,c,d)+mj+ti)
  << gg(a,b,c,d,mj,s,ti) 表示 a=b+((a+(g(b,c,d)+mj+ti)
  << hh(a,b,c,d,mj,s,ti) 表示 a=b+((a+(h(b,c,d)+mj+ti)
  << ii(a,b,c,d,mj,s,ti) 表示 a=b+((a+(i(b,c,d)+mj+ti)
  << 这四轮(64步)是:

  第一轮

   ff(a,b,c,d,m0,7,0xd76aa478)
   ff(d,a,b,c,m1,12,0xe8c7b756)
   ff(c,d,a,b,m2,17,0×242070db)
   ff(b,c,d,a,m3,22,0xc1bdceee)
   ff(a,b,c,d,m4,7,0xf57c0faf)
   ff(d,a,b,c,m5,12,0×4787c62a)
   ff(c,d,a,b,m6,17,0xa8304613)
   ff(b,c,d,a,m7,22,0xfd469501)
   ff(a,b,c,d,m8,7,0×698098d8)
   ff(d,a,b,c,m9,12,0×8b44f7af)
   ff(c,d,a,b,m10,17,0xffff5bb1)
   ff(b,c,d,a,m11,22,0×895cd7be)
   ff(a,b,c,d,m12,7,0×6b901122)
   ff(d,a,b,c,m13,12,0xfd987193)
   ff(c,d,a,b,m14,17,0xa679438e)
   ff(b,c,d,a,m15,22,0×49b40821)

  第二轮

   gg(a,b,c,d,m1,5,0xf61e2562)
   gg(d,a,b,c,m6,9,0xc040b340)
   gg(c,d,a,b,m11,14,0×265e5a51)
   gg(b,c,d,a,m0,20,0xe9b6c7aa)
   gg(a,b,c,d,m5,5,0xd62f105d)
   gg(d,a,b,c,m10,9,0×02441453)
   gg(c,d,a,b,m15,14,0xd8a1e681)
   gg(b,c,d,a,m4,20,0xe7d3fbc8)
   gg(a,b,c,d,m9,5,0×21e1cde6)
   gg(d,a,b,c,m14,9,0xc33707d6)
   gg(c,d,a,b,m3,14,0xf4d50d87)
   gg(b,c,d,a,m8,20,0×455a14ed)
   gg(a,b,c,d,m13,5,0xa9e3e905)
   gg(d,a,b,c,m2,9,0xfcefa3f8)
   gg(c,d,a,b,m7,14,0×676f02d9)
   gg(b,c,d,a,m12,20,0×8d2a4c8a)

  第三轮

   hh(a,b,c,d,m5,4,0xfffa3942)
   hh(d,a,b,c,m8,11,0×8771f681)
   hh(c,d,a,b,m11,16,0×6d9d6122)
   hh(b,c,d,a,m14,23,0xfde5380c)
   hh(a,b,c,d,m1,4,0xa4beea44)
   hh(d,a,b,c,m4,11,0×4bdecfa9)
   hh(c,d,a,b,m7,16,0xf6bb4b60)
   hh(b,c,d,a,m10,23,0xbebfbc70)
   hh(a,b,c,d,m13,4,0×289b7ec6)
   hh(d,a,b,c,m0,11,0xeaa127fa)
   hh(c,d,a,b,m3,16,0xd4ef3085)
   hh(b,c,d,a,m6,23,0×04881d05)
   hh(a,b,c,d,m9,4,0xd9d4d039)
   hh(d,a,b,c,m12,11,0xe6db99e5)
   hh(c,d,a,b,m15,16,0×1fa27cf8)
   hh(b,c,d,a,m2,23,0xc4ac5665)

  第四轮

   ii(a,b,c,d,m0,6,0xf4292244)
   ii(d,a,b,c,m7,10,0×432aff97)
   ii(c,d,a,b,m14,15,0xab9423a7)
   ii(b,c,d,a,m5,21,0xfc93a039)
   ii(a,b,c,d,m12,6,0×655b59c3)
   ii(d,a,b,c,m3,10,0×8f0ccc92)
   ii(c,d,a,b,m10,15,0xffeff47d)
   ii(b,c,d,a,m1,21,0×85845dd1)
   ii(a,b,c,d,m8,6,0×6fa87e4f)
   ii(d,a,b,c,m15,10,0xfe2ce6e0)
   ii(c,d,a,b,m6,15,0xa3014314)
   ii(b,c,d,a,m13,21,0×4e0811a1)
   ii(a,b,c,d,m4,6,0xf7537e82)
   ii(d,a,b,c,m11,10,0xbd3af235)
   ii(c,d,a,b,m2,15,0×2ad7d2bb)
   ii(b,c,d,a,m9,21,0xeb86d391)

  常数ti可以如下选择:

  在第i步中,ti是4294967296*abs(sin(i))的整数部分,i的单位是弧度。(4294967296等于2的32次方)
所有这些完成之后,将a、b、c、d分别加上a、b、c、d。然后用下一分组数据继续运行算法,最后的输出是a、b、c和d的级联。

  当你按照我上面所说的方法实现md5算法以后,你可以用以下几个信息对你做出来的程序作一个简单的测试,看看程序有没有错误。

   md5 (“”) = d41d8cd98f00b204e9800998ecf8427e
   md5 (“a”) = 0cc175b9c0f1b6a831c399e269772661
   md5 (“abc”) = 900150983cd24fb0d6963f7d28e17f72
   md5 (“message digest”) = f96b697d7cb7938d525a2f31aaf161d0
   md5 (“abcdefghijklmnopqrstuvwxyz”) = c3fcd3d76192e4007dfb496cca67e13b
   md5 (“abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789″) = d174ab98d277d9f5a5611c2c9f419d9f
   md5 (“12345678901234567890123456789012345678901234567890123456789012345678901234567890″) = 57edf4a22be3c955ac49da2e2107b67a

  如果你用上面的信息分别对你做的md5算法实例做测试,最后得出的结论和标准答案完全一样,那我就要在这里象你道一声祝贺了。要知道,我的程序在第一次编译成功的时候是没有得出和上面相同的结果的。


  MD5的安全性

  md5相对md4所作的改进:

   1. 增加了第四轮;

   2. 每一步均有唯一的加法常数;

   3. 为减弱第二轮中函数g的对称性从(x&y)|(x&z)|(y&z)变为(x&z)|(y&(~z));

   4. 第一步加上了上一步的结果,这将引起更快的雪崩效应;

   5. 改变了第二轮和第三轮中访问消息子分组的次序,使其更不相似;

   6. 近似优化了每一轮中的循环左移位移量以实现更快的雪崩效应。各轮的位移量互不相同。
 

     

2005年01月05日

     2005年1月5日,新年北京第一场雪.

     晚上回宿舍,宿舍楼旁的车都已积了厚厚的雪,上面似乎写了什么

    以为又是什么I LOVE YOU 之类….

    结果:  “    办证 133….    “   !

    真是敬业

2004年12月30日

 在FLASH中,动画是逐帧播放的,帧中的代码也是逐帧执行的.

eg1. 若在第一帧中写入:

     gotoAndStop(2);
     trace(“frame1″);

第2帧中写入:

     stop();
     trace(“frame2″);

执行后输出:”frame1,”frame2″; 可见是先将帧中的程序先执行完或读入之后在执行其中的GOTO语句.

eg2.若当前帧程序出现错误,则跳转到下一帧

     第一帧:

    stop();
     }
     trace(“frame1″);

   第二帧:

   stop();
   trace(“frame2″);

输出:

**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 2: Unexpected ‘}’ encountered
     }

Total ActionScript Errors: 1   Reported Errors: 1

frame2

出错之后不执行,错误代码前后均未执行:stop();和trace();

小研究下,欢迎讨论:)

2004年12月28日

An ActionScript 2.0 Primer for ActionScript 1.0 Folk: Part Three

by Joey Lott (www.person13.com)

In parts two of this series I introduced you to the ActionScript 2.0 class structure and syntax. We looked at the basics of creating an ActionScript 2.0 class including using packages, public/private/static class members, getter and setter methods, and so forth. But two of the things that we didn’t talk about were inheritance and interfaces. In this third part I’ll discuss each of these topics in more detail.
Understanding Inheritance
Inheritance is not new to ActionScript 2.0 classes as a concept, but it may be a somewhat unfamiliar topic to some. And as such, it bears a little introductory explanation.
Inheritance refers to hierarchical relationships that can exist between classes. Classes can be defined such that they are a subclass of a superclass, meaning that the subclass automatically inherits all the members of the superclass without having to explicitly redefine them. This is a very important and beneficial feature with regard to classes because it allows for greater levels of abstraction. And greater levels of abstraction mean you get to have much more efficient workflow.
Here’s an example to help you understand how inheritance is beneficial: Let’s say you want to create a Car class similar to the class you created in part two of this series of articles. Now clearly a Car is one of many types of vehicles including Boat, Train, Plane, etc. While all of the vehicles are sufficiently different that they each warrant their own class, they also share some common characteristics. All of the aforementioned vehicles could have properties indicating the passenger capacity and the number of miles it has traveled. In addition, each vehicle is capable of moving, and as such, you could create a method that would move the vehicle at a given rate of speed.
If you create a superclass such as Vehicle, that contains all the common characteristics and functionality of the classes such as Car, Boat, Train, and Plane, then you only have to define that common code in one place rather than repeating it in each class. Creating a superclass does not require any special techniques. You create the class just as with any class you have written up to now. The additional techniques required in setting up inheritance are all within the subclasses.
Extending a Superclass
To create a subclass you must tell Flash what class you want to use as the superclass. In ActionScript OO (Object-Oriented) terminology we say that a subclass extends a superclass. In the case of our example we want a class such as Car to extend the superclass Vehicle. In order to tell Flash to create this hierarchical relationship just use the extends keyword in the subclass declaration as follows:
class Subclass extends Superclass {
}

So in the case of the Car and Vehicle example the basic Car class declaration would look like this:
class Car extends Vehicle {
}

Once you’ve defined the Car class to extend the Vehicle class, then all the properties and method of the Vehicle class are automatically accessible within the Car class.
Calling and Overriding Superclass Methods
Often times you’ll want a subclass to inherit a superclass’s method exactly as they are implemented within the superclass. In such cases you don’t need to do anything within the subclass defintion with respect to those methods. But in other cases you will want to define a specialized implementation of one of those methods within the subclass. We call this overriding a method because the subclass defines its own implementation which effectively overrides the inherited version.
When you override a method you have several options:
* You can override the method completely such that the superclass method’s implementation is disregarded altogether.
* You can override the method such that the superclass’s method is still called, but the subclass implementation adds some additional functionality.
In order to completely override a superclass method all you need to do is define a method with the same name in the subclass in which there are no references to the superclass method. For example, if the superclass has a method such as:

// Method defined in the superclass. 
public function display():Void {
trace("This is the superclass method.");
}


Then you could define a subclass implementation of the method that disregards the superclass method with the following:

// Method defined in the subclass.
public function display():Void {
  trace("This is the subclass method.");
} 


However, any time you want to create a subclass implementation of a method that also calls the superclass implementation, you can use the super keyword to reference the superclass and explicitly call the superclass’s method from within the subclass implementation. For example, the display() method example in the subclass could be rewritten as follows so that it also calls the superclass’s implementation:

// Method defined in the subclass that also calls the superclass method. 
public function display():Void {
super.display();
trace("This is the subclass method.");
}


When the display() method is calls from an instance of the subclass it will display the following in the Output panel:

This is the superclass method. 
This is the subclass method.


You can use the super reference at any point within the subclass. For example, if you call super(), then it references the constructor method of the superclass. This is useful when you want the subclass constructor to perform some actions unique to the subclass, but you also want to call the superclass constructor with some particular values passed to it. The only caveat is that the superclass constructor must always be called on the first line within the subclass constructor if you explicitly call it. Otherwise you will get a compilation error.
Creating a Vehicle and Car class
You’ve had a chance to read some of the theory. Now let’s apply that theory in a simple exercise. In this example you’ll have the chance to create a Vehicle class and a Car subclass. If you completed the exercise from part two of this series of articles, then you’ll have a pretty easy time following along with the functionality in this exercise. If you didn’t complete the exercise from part two and you find that you feel a little confused about the functionality in this example, you might want to go and review that previous example from part two.
1. If you didn’t already do so, create a package directory structure for the package com.person13 within a directory in your Flash classpath. For example, if D:\ActionScriptClasses is in your Flash classpath, create D:\ActionScriptClasses\com\person13.
2. Open a new ActionScript file.
3. Add the following code to the file:

class com.person13.Vehicle { 
private var _nPassengers:Number;
private var _nMiles:Number;
private var _nInterval:Number;
function Vehicle(nPassengers:Number, nMiles:Number) {
_nPassengers = nPassengers;
miles = nMiles;
}
public function get passengers():Number {
return _nPassengers;
}
public function get miles():Number {
return _nMiles;
}
public function set miles(nMiles:Number):Void { if(nMiles >= 0) {
_nMiles = nMiles;
}
else {
_nMiles = 0;
}
}
public function move(nMPH:Number):Void {
if(nMPH == null || nMPH <= 0) {
clearInterval(_nInterval);
}
else {
_nInterval = setInterval(this, "increment", 1000, nMPH);
}
}
private function increment(nMPH:Number):Void {
_nMiles += nMPH;
}
}


4. Save the file as Vehicle.as to the com/person13 directory.
5. If you completed the exercise in part two of this series of articles, then open the Car.as file you created previously (should already exist in the com/person13 directory). Otherwise, open a new ActionScript file.
6. Modify the code or add the following code to the file:

// The Car class extends Vehicle so it will inherit all the properties
// and methods of the superclass. 
class com.person13.Car extends com.person13.Vehicle{
// Declare the properties that are specific to Car. The other properties // are inherited, and you don't need to redeclare them.
private var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
function Car(sMake:String, sModel:String, nYear:Number, nPassengers:Number, nMiles:Number) {
// Call the superclass constructor, then assign the values for the
// Car-specific properties.
super(nPassengers, nMiles);
_sMake = sMake;
_sModel = sModel;
year = nYear;
}
public function get make():String {
return _sMake;
}
public function get model():String {
return _sModel;
}
public function get year():Number {
return _nYear;
}
public function set year(nYear:Number):Void {
if(nYear >= 1886) {
_nYear = nYear;
}
else {
_nYear = 1886;
}
}
// Define a method called drive() that just calls the move() method
// that it inherits from Vehicle. This is not necessary, but it just
// means that you can declare a more intuitive API for the Car class
// since the term drive is more specifically related to cars than
// the generic term move.
public function drive(nMPH:Number):Void {
move(nMPH);
}
}


7. Save the file in the same com/person13 directory to which you saved Vehicle.as. If the file is new (as in you aren’t modifying the Car.as file from the exercise from part two) then name the file Car.as. Otherwise, the file should already be named Car.as.
8. If you completed the exercise from part two then open the same .fla you used to test that example. Otherwise create a new .fla.
9. If you already completed the .fla for the previous exercise then you don’t need to modify the code. If you are creating a new .fla, then add the following code to the first frame of the default layer:

import com.person13.*; 
function displayMileage(carObj:Car):Void {
trace(carObj.miles);
}
var car:Car = new Car("Oldsmobile", "Alero", 2000, 5, 43000);
car.drive(65);
setInterval(displayMileage, 100, car);


10. Test the movie. You should see the miles value continually displayed in the Output panel, incrementing approximately every second.
[Optional]
11. Open a new ActionScript file.
12. Add the following code in the file:

class com.person13.Plane extends com.person13.Vehicle{ 
private var _sMake:String;
private var _sModel:String;
function Plane(sMake:String, sModel:String, nPassengers:Number, nMiles:Number) {
super(nPassengers, nMiles);
_sMake = sMake;
_sModel = sModel;
}
public function get make():String {
return _sMake;
}
public function get model():String {
return _sModel;
} public function fly(nMPH:Number):Void {
move(nMPH);
}
}


13. Save the file as Plane.as in the com/person13 directory.
14. Open a new .fla.
15. Add the following code to the first frame of the default layer:

import com.person13.*; 
function displayMileage(obj:Plane):Void {
trace(obj.miles);
}
var plane:Plane = new Plane("Boeing", "747", 300, 100000);
plane.fly(400);
setInterval(displayMileage, 100, plane);


16. Test the movie.
Extending Subclasses
You are not limited to creating only one level of inheritance. You can also extend a subclass…or a subclass of a subclass for that matter. For example, you could create a Ferrari class that extends Car or a Lear class that extends Plane. The process is the same when extending any class regardless of whether the superclass happens to be a subclass of another class or not.
Understanding Interfaces
Interfaces are probably one of the least understood programming concepts. Interfaces are quite simply a set of rules with which classes can be in accordance. When you define a class to agree to the rules of an interface we say that the class implements the interface.
So what types of rules or guidelines does an interface define? In specific terms, an ActionScript 2.0 interface tells Flash what methods a class must implement including the following information
* the name of the method
* what parameters it should expect
* the public declaration of the method (you cannot declare private or static methods in an interface)
* the return type

An interface may not contain any of the following:
* property declarations
* method implementations
* private or static method declarations

A class can then implement an interface. When the class implements an interface it agrees to have, perhaps among other things, methods that match the methods declared in the interface. If it does not contain the matching methods then Flash will generate an error when you try to compile.
Benefits of Interfaces
Often developers do not initially understand the potential benefits of interfaces. After all, what is there to be gained by using interfaces? At first it would seem that you go to an extra effort with no substantial payback. An interface does not provide any functionality because it does not actually implement any of the methods it declares.
The real advantages of interfaces are somewhat subtle and in order to seem them you have to take a step back and look at the bigger picture. If you are creating a single class for a single application then there is really no point whatsoever in writing an interface for the class. And not every class should necessarily implement an interface. But when you are working within a larger scope – larger timeframes, larger projects, larger teams – then interfaces help you to create basic blueprints that can improve workflow not only when developing classes, but also when utilizing the classes.
For example, let’s say you’re working on a team to create a group of classes such as Vehicle, Animal, Wind, and Planet. While each of these classes is likely to have varying APIs, they might all share one thing in common – they can all move. If moving is something that you want to implement in each of the classes, you might want to create an IMoveable interface that all of the classes can implement. The IMoveable interface would declare the move() method such that each implementing class would agree to then have a move() method. This is helpful for the team. When you create the interface and determine which classes will implement it, then the developer working on the class already knows what methods to write, and it provides standardization across the class APIs. The other benefit is for the developer who is utilizing a class. If you, as a developer using a class, happen to know that the class implements a particular interface, then you already know something about its API.
A class can implement multiple interfaces. And for that reason interfaces are often utilized as a form of multiple inheritance in languages that don’t support actual multiple inheritance. In ActionScript a class can only extend one other class. For example, the Car class extends Vehicle, and therefore it cannot extend any other classes. But Car can implement multiple interfaces (at the same time as it extends Vehicle.) For example, Car could implement interfaces such as IDrivable, IManufacturable, ISellable.
Creating an Interface
You’ve read the theory. Now let’s look at declaring and defining an interface. Since you already know the syntax and structure for classes, you’re not going to learn too much that is new.
The interface declaration looks almost identical to the class declaration. The only difference is that an interface declaration uses the interface keyword instead of the class keyword. For example:

interface IMoveable { 
// Interface definition.
}


An interface can only specify which methods an implementing class must have. So you will not be declaring any properties within your interfaces. And you should not define/implement any of the methods within the interface. Each of the method declarations should consist of only the following elements (this is reiterated from previous):
* the name of the method
* what parameters it should expect
* the public declaration of the method
* the return type

Here’s an example of a complete IMoveable interface:

interface IMoveable { 
public function move(nMPH:Number):Void;
}


Just as with classes, you can package interfaces. For example, if you want to package IMoveable in the com.person13 package you can declare it as follows:

interface com.person13.IMoveable { 
public function move(nMPH:Number):Void;
}


And you can also extend interfaces just like classes. So, for example, if you wanted to create a IDrivable interface to extend IMoveable, it might look something like the following:

import com.person13.IMoveable 
interface com.person13.IDrivable extends IMoveable {
public function drive(nMPH:Number):Void;
}


Implementing an Interface
Once you’ve defined an interface you can tell a class you want it to implement the interface using the implements keyword followed by a comma-delimited list of the interfaces you want it to implement. For example, if you want the Vehicle class to implement the IMoveable interface the beginning of the class declaration might look like:

class com.person13.Vehicle implements com.person13.IMoveable { 


Or, of course, you could use an import statement to first import the interface:

import com.person13.IMoveable; 
class com.person13.Vehicle implements IMoveable {


In the hypothetical scenario in which the Car class implements multiple interfaces such as IDrivable, IManufacturable, and ISellable, the first part of the class declaration might look like:

import com.person13.*; 
class com.person13.Car implements IDrivable, IManufacturable, ISellable {


When a class implements an interface, Flash will check during compile time to ensure that the class has all the correct implementations. If a method is missing or incorrectly declared in the class so as to not adhere to the interface, Flash will display an error message letting you know.
Conclusion
That wraps up the third article in this series. Let me know if you have any questions or comments about anything that has been covered. Keep an eye out for another installment. Next I’ll talk about error handling using try-catch-finally and throw – yet another new feature in ActionScript 2.0.
As always, thank you.

An ActionScript 2.0 Primer for ActionScript 1.0 Folk: Part Two

by Joey Lott (www.person13.com)

As promised in Part One of this article, in this second part we’ll examine the new class syntax in ActionScript 2.0. Before we get started, if you have questions regarding general object-oriented concepts, including classes, then you may want to first check out these two articles:

http://www.oreillynet.com/pub/a/javascript/2003/08/12/actionscriptckbk.html
http://www.oreillynet.com/pub/a/javascript/2003/08/19/actionscriptckbk.html

The two articles discuss object-oriented concepts and creating classes in ActionScript 1.0, so you don’t necessarily need to memorize all the details of the ActionScript 1.0 techniques. But the articles should give you a pretty good introduction to what classes and objects are in a general sense. Once you have that background this article will likely make more sense to you.

ActionScript 2.0 Class Structure

While I could attempt to draw comparisons between ActionScript 1.0 “class” structure and ActionScript 2.0 class structure, it would likely be more confusing that clarifying. The truth is that ActionScript 2.0 class structure is fundamentally different than that of ActionScript 1.0. If you have any background in creating classes in other languages such as Java or C#, or even VB or PHP, then you’ll likely shout a loud hoorah for the new formal class structure in ActionScript. If you’re only prior experience with creating classes was with ActionScript 1.0, then don’t fret too much. You’re sure to find that although the syntax in ActionScript 2.0 is different, it is much more intuitive. After a week writing ActionScript 2.0 classes you’ll wonder how you ever managed with ActionScript 1.0.

To begin with, I’ll highlight a few of the key points of the new class structure and syntax, then we’ll look at some of them more closely.

* ActionScript 2.0 classes must be defined in .as files, and there can only be one class per file.
* ActionScript 2.0 classes are declared using the new class keyword followed by the name of the class and then the body of the class surrounded in curly braces. For example:
class Car {
// Class definition…
}

* ActionScript 2.0 classes can be in packages. ActionScript 2.0 supports the import keyword in order to import entire packages or select classes within packages.
* ActionScript 2.0 class members can be declared as public, private, and static.
* ActionScript 2.0 classes can extend other classes using the extends keyword in the class declaration.
* ActionScript 2.0 classes can implement interfaces.

Whew! If any of that sound scary or new to you, keep on reading. I’m going to explain each of these parts in more detail and with examples you can try on your own (assuming you have a copy of Flash MX 2004 or Flash MX Professional 2004.)

Defining ActionScript Class Files

If you’re not familiar with other languages such as Java or C# then storing classes in their own files may be a new concept. Particularly so if you’ve worked with ActionScript 1.0 in which you could define multiple classes not only within a single .as file, but even within an .fla file.
There are plenty of reasons why it’s advantageous to store all your classes, one per file, in external .as files. The core benefit is, of course, better organization. It’s just simply much easier to store, locate, maintain, and distribute your classes when they’re organized well. If you’re defining classes in all kinds of places, then it becomes a mess rather quickly. Of course, if you were only working with two or three classes, this would not necessarily pose a big problem. But ActionScript 2.0 ushers in a new paradigm for ActionScript. Developers can create and share libraries of classes that provide pre-built functionality. Rather than reinventing the wheel each time people can begin to build upon their own previous work and the work that others have contributed. You can see how Macromedia has already jumpstarted this with their set of standard classes that you can find in the First Run/Classes directory (and subdirectories) of your Flash MX 2004 installation.
So unlike ActionScript 1.0 classes, all ActionScript 2.0 classes absolutely must be saved in external .as files. Further more, these files must be saved such that the file name matches the name of the class. For example, if the class is named Car, then the file must be named Car.as.

Working with Packages

Class files may be stored in packages. If you’re not familiar with packages (also called namespaces in the .NET world) they are simply a way of organizing your classes. There are two aspects to a package. First, the class definition must specify the package in its declaration. We’ll look more closely at that part in the next section. Secondly, the .as file must be saved in a corresponding directory or directories. For example, if the package for a class is com.person13 then the .as file for that class must be saved in a directory structure of com/person13.

There are two primary benefits to working with packages. The most obvious one is that it provides you with a way to organize your class files so that you can locate them quickly. For example, if you look in the set of classes that ship with Flash MX 2004 (in the First Run/Classes directory) you’ll see that many of the classes for the UI components are organized within the mx.controls package, and are therefore saved in the mx/controls directory. The second benefit of packages is that it helps to avoid possible name conflicts. You cannot have two classes with the same name in the same package for the obvious reason that Flash wouldn’t have a way of knowing which one you want to use. So if you didn’t use any packages and saved all your classes in the same directory you would potentially run into this problem. Of course, if you are writing all the classes then you have the ability to easily make sure you give each class a unique name. But when you download and install others’ classes, you don’t have that same control. So when classes are stored in packages it helps to make sure that these types of naming issues don’t occur. For example, the class Car in the com.person13 package and the class Car in the com.ejepo package don’t create any naming conflicts with Flash.

Defining Your Classpath

By default Flash looks first to the First Run/Classes directory within your Flash installation when trying to find class files. If it does not find a specified class in that directory then it next looks to the same directory in which the Flash or ActionScript document is saved.
The classpath is the list of directories to which Flash looks for class files. You can also specify additional directories for the classpath. And, if you want, you can change the order in which Flash looks to these directories. In order to edit the classpath choose Edit>Preferences, and then select the ActionScript tab. Click on the ActionScript 2.0 Settings to bring up the ActionScript Preferences dialog box. Use the + button to add new directories, the – button to remove directories, and the arrow buttons to reorder them.


Figure 1: defining the classpath

As you can see in Figure 1, I’ve added the directory D:\ActionScriptClasses to my classpath. This means that the third place that Flash will look for class files is now D:\ActionScriptClasses. (Incidentally, $(LocalData) resolves to the First Run directory of your Flash installation.) Adding a custom directory to the classpath can be a good idea for a few reasons:
* It can be easier to browse to a directory such as D:\ActionScriptClasses than to the directory in which Flash stores all classes that ship with Flash.
* It is easier to manage your files if you save all your custom classes in a directory other than the directory into which Flash stores classes that ship with Flash.

Understanding Private and Public Members

A class is composed of members – properties and methods. Unless you used some convoluted or undocumented features of ActionScript 1.0, all ActionScript 1.0 members were public. When we say that a member is public, it means that it can be accessed from outside of the class definition. For example, if you create a Car class with a property named make, and that property can be accessed from an instance of the Car class, then the property is public. But there are plenty of times in which you don’t want the properties and methods of a class to be publicly accessible. A class may have properties and variables that are used only internally, and that don’t need to be exposed publicly. In such cases you can declare a member to be private.

Note: If you’ve used other languages such as Java or C# then you should note that a private member in ActionScript 2.0 behaves like a protected member in Java or C#.

In order to declare a member as public or private you can use the public and private keywords, respectively. For example, the following declares a private property:

private var _nInterval:Number;


By convention you can use the underscore character as the first character in a private property’s name to help differentiate between local variables, parameters, and private properties within the class.

We’ll take a look at declaring public and private members in context within an upcoming section. An example of private and public members should help to clarify this topic, and in an upcoming section you’ll create a custom class that uses both public and private members.

Note: If you don’t specify either public or private then the default is public.

Understanding Static Members

Static members are members that are accessed directly from the class, and not from instances. This is not a new concept to ActionScript 2.0. In fact, since Flash 5 you have seen built-in classes with static members. For example, the Math class is comprised entirely of static members. Rather than creating an instance of the Math class and then accessing the properties and methods from a instance, you always access the properties and methods directly from the class itself. For example:

trace(Math.cos(3.14));

Notice that the cos() method is accessed directly from the Math class, thus it is a static method.
In order to create a static member in an ActionScript 2.0 class you use the static keyword in the declaration. And static members can be further modified to be either public or private, just like non-static members. Here’s an example of a public static member declaration.

public static var classname = “Car”;

Declaring a Class

If we look at a class structure in very simplistic terms, there are four basic parts:
* The class declaration consisting of the keyword class and the name of the class.
* Property declarations.
* Constructor declaration.
* Method declarations.

Let’s examine each of these parts a little more closely:

Class declaration

To declare a class you use the keyword class followed by the name of the class. Then you enclose the class definition in curly braces. For example:

class Car {
// Class definition.
}


If you want to place the class in a package then you need to indicate the package as part of the class name in the declaration. We call the name of a class that includes the package the fully-qualified class name. For example, if you wanted to place the Car class in the package com.person13, then the class declaration would look like this:

class com.person13.Car {
// Class definition.
}


And, of course, when you place a class in a package, you must be sure to save the class file to the corresponding directory. In the case of the com.person13.Car class the file Car.as should be saved in a directory structure of com/person13 where the com directory is located within the Flash classpath. (For example, if your classpath includes D:\ActionScriptClasses, then you could save the file as D:\ActionScriptClasses\com\person13\Car.as.)


Property Declarations

You must declare all properties within the curly braces of a class definition. You must also declare all properties outside of any methods. By convention you should declare all the properties at the top of the class definition. For example:

class com.person13.Car {

private var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;

// Rest of class definition.

}


Constructor Declaration

After you’ve declared the properties within the class, you should next declare the constructor. Technically, if you don’t declare a constructor explicitly, Flash will create an implicit empty constructor for you. But even if your constructor does not do anything, it is still good form to declare the constructor explicitly.
Remember, the constructor is a special method that shares the same name as the class. The constructor can be used within a new statement to create new instances of the class. The constructor should be declared just like a regular function, and even though it can accept parameters, it should not return any values. Here’s an example of the Car class with a constructor:

class com.person13.Car {

private var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;

function Car(sMake:String, sModel:String, nYear:Number, nMiles:Number) {

_sMake = sMake;
_sModel = sModel;
_nYear = nYear;
_nMiles = nMiles;

}

// Rest of class definition.

}

Unlike some other languages, you cannot have overloaded constructors in ActionScript 2.0.

Declaring Methods

Next you can declare the methods of your class. You declare methods just like standard functions, using the function keyword and the same exact syntax. Remember, a method is a function, but it is associated with a class. Because you declare the function within the class, Flash automatically knows to associate it with the class. The only differences between standard functions and methods are that you can declare methods to be public, private, and static if appropriate. Here’s an example of the same Car class with two methods – one public and one private.

class com.person13.Car {

private var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;

function Car(sMake:String, sModel:String, nYear:Number, nMiles:Number) {

_sMake = sMake;
_sModel = sModel;
_nYear = nYear;
_nMiles = nMiles;

}

public function drive(nMPH:Number):Void {

if(nMPH == null || nMPH == 0) {

clearInterval(_nInterval);

}
else {

_nInterval = setInterval(this, “increment”, 1000, nMPH);

}

}

private function increment(nMPH:Number):Void {

_nMiles += nMPH;

}

}

Working with Getter/Setter Methods

Getter and setter methods are special methods that are accessible outside the class as properties, but are defined within the class as methods. Among the potential advantages of getter and setter methods is that these methods allow you to create members that work like properties external to the class, but that can have sophisticated logic built into them. In the case of our Car class example, we might want to make sure that the value for the year of the car is never set earlier than 1886 (the year the first automobile was invented) and that the number of miles is never set less than 0. Additional benefits of getter and setter methods are:
* They allow us to work with property names such as _nMiles within the class, but to expose the values publicly with more user-friendly property names such as miles.
* They allow us to create read-only and write-only properties.
* They allow us to create virtual properties – properties that don’t correspond to any one property within the class, but that are generated based on a mixture of internal values.

A getter method should never accept any parameters and should always return a value. The syntax for a getter method is as follows:

function get externalPropertyName():ReturnType {

// Method definition, including return statement.

}

The method can, like other methods, be modified with the public and static keywords as well, but you may not declare a getter method as private.

Here’s an example of a simple getter method that returns the value of _nMiles as the property miles.

public function get miles():Number {

return _nMiles;

}

Setter method syntax is very similar to the syntax for a getter method except that it should always accept a parameter, never return a value, and use the set keyword instead of get. Here’s the basic syntax:

function set externalPropertyName(parameterName:DataType):Void {

// Method defintion.

}

And just like getter methods, you can modify setter methods with the public and static keywords, but not with private. Here’s an example of a setter method that assigns a new value to the private property _nMiles. Notice that it checks to make sure the value is 0 or greater. If not, it uses the default value of 0.

public function set miles(nMiles:Number):Void {

if(nMiles >= 0) {

_nMiles = nMiles;

}

else {

_nMiles = 0;

}

}

Importing Classes

When you place classes in packages, you need to always use the fully-qualified class name when you reference the class. That means that if you have created com.person13.Car, then in order to create an instance of the class your constructor statement might look something like this:

var car:com.person13.Car = new com.person13.Car(“Oldsmobile”, “Alero”, 2000, 43000);

There is, however, a shortcut. You can use the import statement to tell Flash what packages and classes you want it to know about without having to specify the package. Then, Flash will automatically assume the package name without you having to specify it each time. Here is an example that imports the Car class and then constructs an instance.

import com.person13.Car;
var car:Car = new Car(“Oldsmobile”, “Alero”, 2000, 43000);


You’ll notice that it is much more readable. Also, when you have many references to the class name, it can save you a lot of time typing.

You can also import all the classes in a package using the * wildcard. For example, the following will import any class in the com.person13 package.

import com.person13.*;

Creating a Class

You’ve had a chance to now see some of the preliminary stuff with regard to ActionScript 2.0 classes, but I can tell you’re ready to jump in and create a class of your own. We’ll start out by creating a class named Car. Just follow the steps that follow:
1. Open a new ActionScript file. If you use Flash MX Professional 2004 then you can use the ActionScript file editor that is in the IDE. Otherwise, you can use your favorite text editor so long as it can save a plain text file.
2. The first code you should add to the file is the class declaration. In order to do this you use the class keyword followed by the class name and then curly braces to surround the class definition. So start by adding the following code to your file:

class com.person13.Car {

}

3. Next declare the five properties. You’ll make each of these properties private. The first four should be fairly self-evident. The last property you’ll use to store the interval ID for an interval method you’ll set in one of the methods.

class com.person13.Car {

private var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;

}

4. Then declare the constructor. In this case, let’s have it accept four parameters and assign those values to the corresponding properties. You’ll notice that in two cases we’re referencing properties that we didn’t declare. That’s because those two properties will be defined with setter methods shortly. We want to set the setter methods in those cases because we want to employ some logic that makes sure the values are valid.

class com.person13.Car {

private var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;

function Car(sMake:String, sModel:String, nYear:Number, nMiles:Number) {

_sMake = sMake;
_sModel = sModel;
year = nYear;
miles = nMiles;

}

}


5. Next, declare some methods for the class. In this case we’ll create a single public method named drive(). Then, we’ll also create a private method named increment() that will get called on an interval once the drive()method has been called with a valid miles per hour parameter.

class com.person13.Car {

private var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;

function Car(sMake:String, sModel:String, nYear:Number, nMiles:Number) {

_sMake = sMake;
_sModel = sModel;
year = nYear;
miles = nMiles;

}

public function drive(nMPH:Number):Void {

if(nMPH == null || nMPH <= 0) {

// If nMPH is null or less than or equal to 0 then
//
we want to tell the car to stop
// driving…We can do that by clearing the interval.

clearInterval(_nInterval);

}
else {

// Otherwise, if nMPH is a number in the valid
// range, then set an interval so
// that the private method increment() is called
// once a second or so.
_nInterval = setInterval(this, “increment”, 1000, nMPH);

}

}

private function increment(nMPH:Number):Void {

// Each time the method is called, update the _nMiles value
// by incrementing it by nMPH. Of course, since the method
// is called once a second, the actual mileage increment is
// about 360 times what it would be. But, hey, we’ve
// got to speed things up a bit so that we can see some
// progress within a short amount of time. ;)
_nMiles += nMPH;

}

}

6. The remaining step is to define the getter and setter methods as shown in the following code:

class com.person13.Car {

private var _sMake:String;
private var _sModel:String;
private var _nYear:Number;
private var _nMiles:Number;
private var _nInterval:Number;

function Car(sMake:String, sModel:String, nYear:Number, nMiles:Number) {

_sMake = sMake;
_sModel = sModel;
year = nYear;
miles = nMiles;

}

public function get make():String {

return _sMake;

}

public function get model():String {

return _sModel;

}

public function get year():Number {

return _nYear;

}

public function set year(nYear:Number):Void {

if(nYear >= 1886) {

_nYear = nYear;

}
else {

_nYear = 1886;

}

}

public function get miles():Number {

return _nMiles;

}

public function set miles(nMiles:Number):Void {

if(nMiles >= 0) {

_nMiles = nMiles;

}
else {

_nMiles = 0;

}

}

public function drive(nMPH:Number):Void {

if(nMPH == null || nMPH <= 0) {

clearInterval(_nInterval);

}
else {

_nInterval = setInterval(this, “increment”, 1000, nMPH);

}

}

private function increment(nMPH:Number):Void {

_nMiles += nMPH;

}

}

7. If you haven’t yet done so, create a com/person13 directory within your Flash classpath. For example, if your classpath includes D:\ActionScriptClasses, then make sure you have created D:\ActionScriptClasses\com\person13.

8. Save the ActionScript class file as Car.as to the com/person13 directory.

9. Open a new Flash document (.fla).

10. On the first frame of the main timeline add the following ActionScript code:

import com.person13.Car;

/ / First, a function that will display the miles property value
// for a Car object.
function displayMileage(carObj:Car):Void {

trace(carObj.miles);

}

// Create the Car object.
var car:Car = new Car(“Oldsmobile”, “Alero”, 2000, 43000);

// Tell the car to start driving at 65 miles per hour (for those of you
// outside of the U.S., you’ll have to work out the conversions to
// kilometers yourself! ;)
car.drive(65);

// Set an interval so that the mileage of the Car object will
// continually display.
setInterval(displayMileage, 100, car);

11. Test the movie.

You should see the mileage of the car displaying in the Output panel. It should increment by 65 once a second or so.

Conclusion

In this article I touched on the basics of ActionScript 2.0 classes. I didn’t yet go into the details of extending classes or implementing interfaces. We’ll save those topics for a third installment on account of this article is already long enough. Thanks for reading.

 

An ActionScript 2.0 Primer for ActionScript 1.0 Folk: Part One

by Joey Lott (www.person13.com)

For those of you who have been developing in Flash and ActionScript for some time, the announcement of ActionScript 2.0 may well have struck you in many different ways. Perhaps there is some excitement about the new frontiers and the new possibilities that ActionScript 2.0 may provide. After all, it’s 2.0, that must represent improvements and new developments, right? On the other hand, the prospect of having to learn new syntax and new features may well send you retreating into a corner or trying to stick your head in the sand. In this article I’d like to foster your excitement and dispel your fears about ActionScript 2.0.

To start, let’s get the terminology straight. The ActionScript that you’ve been writing in Flash 5 and Flash MX is now referred to as ActionScript 1.0. In other words:

trace(“ActionScript 1.0″ == “Flash 5/MX ActionScript”); // Displays: true

ActionScript 2.0 is a new feature included in both Flash MX 2004 and Flash MX Professional 2004, and in most respects it is very much the same language as ActionScript 1.0. That means that the majority of what you have learned with ActionScript 1.0 still applies to ActionScript 2.0. (I can hear a few sighs of relief already.) In fact, unless you’ve been writing custom classes in ActionScript, the differences between ActionScript 1.0 and ActionScript 2.0 are rather negligible. And, for those of you die-hard ActionScript 1.0 fans, you still have the option of developing applications using ActionScript 1.0. (Be aware, however, that mixing ActionScript 1.0 and ActionScript 2.0 code may or may not work.)

So what are the major features in ActionScript 2.0 that differentiate it from ActionScript 1.0? Glad you asked.

* Strong typing. This means that you can declare variables such that they can hold only one type of data. For example, you can declare a variable that is a MovieClip type, a String type, or a Color type. This also applies to function parameters. Strong typing helps to ensure that you are using good coding practices, and it helps to eliminate many mistakes that can arise from the loosely typed variables of ActionScript 1.0.
* Function return typing. This is a feature similar to strong typing. If a function returns a value then you can specify the type of value that it should return. If the function is not intended to return a value then you can specify that the function does not return a value. This is yet another feature that helps avoid many coding mistakes, and it works hand in hand with strong typing. For example, if you declare a function to return a String, and you try to assign that value to a variable typed as Number, then Flash will generate an error.
* Formal class syntax. This is, perhaps, the biggest new feature of ActionScript 2.0. ActionScript 1.0 lacks a formal class syntax, and instead, uses prototypes. ActionScript 2.0 supports public, private, and static class members, inheritance, and interfaces.

Those are some of the primary features of ActionScript 2.0. If you’re still reading, then let’s take a closer look at some of these points. In part one of this article we’ll look at strong typing and function return typing. The new formal class syntax is a big topic, and we’ll take a look at that in part two.

Strong Typing

ActionScript developers have long been spoiled with lose typing. That means that in ActionScript 1.0 you can declare a variable, assign a string value, and then assign a number value to the same variable:

var sProduct = “Flash MX 2004″;
sProduct = 6;

Of course, when you look at a simplified example like the preceding one, it is clear that a variable should only ever have one type of value. The variable sProduct should always contain a string value such as “Flash MX 2004″ or “Dreamweaver MX 2004″, but it should not have a number value such as 6. This just makes sense. After all, in your application you want to be able to rely that the variable, when accessed at any point, will return a type of value that is useable. For example, if you want to display the value of sProduct to the user then it is important that you can rely on it being a string value and not an object of some kind. Make sense? Good.

ActionScript 1.0 tends to lend itself to poor programming practices…and to mistakes of assigning incorrect data types to variables. Many hours have been spent debugging applications just to isolate a line in which the wrong type of data was assigned. Strong typing is a compile-time (meaning it does not verify data types at runtime) feature of ActionScript 2.0 in which you can declare a variable to be of a particular data type. If you accidentally attempt to assign the wrong type of data to that variable, then when you use the check syntax feature or when you try to export/publish the application, Flash will give you an error message indicating where there is a type mismatch in your code. In order to declare a variable with strong typing, you must use the var keyword first, followed by the variable name, a colon, and the data type. All data type names are capitalized. Here is an example in which we declare sProduct as String:

var sProduct:String = “Flash MX 2004″;

After sProduct has been declared as String, if you attempt to assign a number value to it, Flash will give you an error. For example, if you attempt this:

sProduct = 6;

Then you will see the following error in the Output panel:

**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 2: Type mismatch in assignment statement: found Number where String is required.
sProduct = 6;

Total ActionScript Errors: 1 Reported Errors: 1

Be sure to only use the var keyword when you are first declaring the variable. If you use the var keyword subsequently, then Flash will think you are declaring a new variable. It will create a new variable with the same name, overwriting the original. For example:

var sProduct = 6;

If you use the preceding code then Flash will create a new variable named sProduct. The new variable will not have any strong typing. The strong typing from the original variable will not be checked against the new variable in such a case and you will not receive any errors.

When you use strong typing you should get code hints with a list of data types after typing the colon. Figure 1 shows this.


Figure 1: code hints for strong data types

Extra Features of Strong Typing

There are at least two extra features with strong typing:

* Strong typing clarifies your code, making it easier for you and others to read it later on. Often times we think we’ll remember what we were thinking, but we don’t. Of course, good commenting and variable naming is extremely important, but strong typing can also help to clarify the intention of particular variables.
* Strong typing provides code hinting without code hinting suffixes.

For most, code hinting in Flash MX was an extremely useful feature, but you had to always use code hinting suffixes to get the code hints. With strongly typed variables in Flash MX 2004, you can get code hints while still using your preferred naming convention. Throughout this article I’ll be using a modified Hungarian notation that uses one, two, or sometimes three character prefixes at the beginning of the variable name. For example, in the previous section I used the variable named sProduct. The “s” prefix indicates that it is a String typed variable. Of course Flash still doesn’t know anything about that. But if you strongly type the variable, then Flash will automatically give you the appropriate code hints when prompted. Here’s an example in which I’ve declared a variable to be a reference to a Color object. Then, subsequently if I type the variable name and a dot, I will get code hints. Figure 2 shows this.

Figure 2: another code hinting example

Function Return Types

You can declare the return type for an ActionScript 2.0 function. This has the benefit of ensuring that you adhere to your own intentions and are consistent within your own code. To specify the return type for a function you should follow the function call operator’s closing parenthesis with a colon and the return data type. This is very similar to the syntax for strongly typing variables. Here’s an example in which I specify the return type for the function to be Number:

function multiply(nA:Number, nB:Number):Number {
  return (nA * nB);
}

In the preceding example you’ll likely notice that I also applied strong typing to the parameters as well as defined the return type for the function. Since the parameters are essentially variables, if you try to assign the wrong data type to them when calling the function, Flash will generate an error. For example, the following code:

trace(multiply(6, “Flash MX 2004″));

Will produce the following error because the second parameter is a string instead of a number:

**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 5: Type mismatch.
trace(multiply(6, “Flash MX 2004″));

Total ActionScript Errors: 1 Reported Errors: 1

Let’s get back to return types, though; The return type on the function assists you in two ways. If you forget to return the correct type then Flash will give you an error message. For example, if you wrote the multiply() function as follows:

function multiply(nA:Number, nB:Number):Number {
  return “Flash MX 2004″;
}

Then you would receive an error such as:

**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 2: The expression returned must match the function’s return type.
return “Flash MX 2004″;

Total ActionScript Errors: 1 Reported Errors: 1

That is because the actual value returned must match the declared return type.

In addition, if you attempt to use the function’s return value in an assignment statement with a variable, Flash checks to make sure the data types match. For example:

function multiply(nA:Number, nB:Number):Number {
  return (nA * nB);
}

var sProduct:String = multiply(6, 5);

The preceding example attempts to assign the return value from multiply() to a variable that is typed as String. Because the return type for multiply() is Number, Flash will generate an error:

**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 5: Type mismatch in assignment statement: found Number where String is required.
var sProduct:String = multiply(6, 5);

Total ActionScript Errors: 1 Reported Errors: 1

A Note About the Benefits

Up to this point we’ve discussed the new strong typing and function return typing features of ActionScript 2.0. For those with experiences with other programming languages that support these features already (for example Java, C#, C++) the benefits are apparent. But for those who have no experience with strongly typed languages, it may actually appear to be much more restrictive and cumbersome. So what are the benefits of these new features?

As we’ve been discussing each of these features I’ve given you some clues as to the potential benefits that strong typing and function return typing can have in your application development. The primary benefits are:

* Reduced errors due to accidental incorrect assignments. This just means that you’ll get compile-time errors to help direct you to where you may have made a mistake rather than having to debug the code on your own.
* Cleaner, clearer code…or at least the potential for cleaner, clearer code.
* Assistance in good coding practices. Believe it or not, good coding practices are actually intended to help you as a developer. Strong typing and function return typing help you write good code that is clear in its intent.
* Code hinting without code hinting suffixes (for strongly typed variables.)

It should be noted that there are many things for which Flash does not check during compile-time. In the discussion on strong typing we saw one such example in which it is possible to declare the same variable more than once. This is not a good practice, and most strongly typed languages will produce an error when you attempt to do such a thing. Remember, Flash MX 2004 is the first release that supports ActionScript 2.0. We may well see many more enhancements in future versions.

Conclusion

Hopefully this has helped introduce you to a few of the new features of ActionScript 2.0 without scaring you too much. In part two we’ll look at the formal class syntax that is introduced in ActionScript 2.0. If you want to be notified when part two is published then please fill out the form below and you will receive an email each time a new article is published on this site.

2004年12月27日
kh0d



kh0d

link: http://www.kh0d.com
designer name: kh0d

很久没看到这样优秀的设计了,只能这样形容,精致。

忍不住去点它,内容似乎已不重要了 :)

只是全用图片,如果用FLASH应该会更有质感和动感。



 

2004年12月26日

最近去了假日酒店就餐,发现那里不会有拿错餐巾的尴尬了!^^


白色为餐巾

点击浏览该文件
 

一个Web系统的界面设计和开发

早在中国IT业方兴未艾之时,计算机应用系统主要以功能实现为主,几乎没有界面设计这个概念。时至今日,随着计算机和网络的不断普及,社会信息化程度日益加深,用户和市场的不断成熟,人们已经不仅仅满足于“够用”,而是更加强调“好用”“易用”;因此,不论是普通最终用户的个人软件,还是企业应用的大型系统,界面设计在系统构建中都成为了一个非常重要的方面。

但是,(至少在中国)由于IT业发展滞后、市场还不够成熟等原因,在绝大多数企业中,界面设计在软件系统开发中还没有获得与之重要性相匹配的一席之地,并且在企业运作和协调中也没有形成成熟的模式和解决方案,如何做好界面设计和开发,仍然是大家不断研究探讨的一个问题。

这篇文章,主要内容是我参加一个面向质检行业的Web系统界面设计和开发工作的过程,包括其间的一些构思和想法;其目的就是希望能和大家一起探讨一下这个问题,希望能供大家参考,起到抛砖引玉的作用。

另外,我同时承担了系统开发和界面设计工作,所以,虽然这是一篇讨论界面设计的文章,我也尽量把文章限制在界面设计范围内,但也有可能包含一些开发和系统设计的内容,请大家辨析清楚,欢迎指正。

1.工作流程

下图,是整个开发过程中与界面设计相关的主要流程工作。

 
此主题相关图片如下:
按此在新窗口浏览图片

从最初需求分析开始,我就加入项目,自始自终参加整个开发过程。

在需求分析阶段,参与了对客户的访问和调研;
在概要设计阶段,参与了部分系统设计分析工作;
在详细设计阶段,完成了整个系统界面设计和Demo制作,并提交用户反馈;
在代码开发阶段,参与了系统表现层的设计开发。

2.需求分析

在需求分析阶段,主要针对界面交互相关问题,对用户进行若干调研。

主要包括以下内容

·受众用户群调查
·系统使用环境调查
·受众用户使用习惯调查
·用户对旧版本软件使用情况调查

这一阶段,由于成本原因,我并没有直接访问客户进行调查。工作主要是提出某些具体问题,由需求调研人员,以问卷或口头问答方式,对客户进行调研。另外,公司经验丰富的客服人员和市场人员,也是非常重要的需求来源之一。

本系统的客户群主要为国家省市下属质检单位,最终受众年龄从年轻到较高龄都有。对于普通国家机关人员,一般对计算机系统和网络不够熟悉,计算机环境一般,甚至比较差,少有配置优良的环境。在这种环境下,用户对计算机使用一般没有使用倾向,大多更适应手工操作。对本系统的前代使用,最主要意见是使用困难,不方便。

还有其他具体调查反馈,如用户基本不使用鼠标右键,年龄较大的用户难以看清密集的较小文字等等。


3.界面设计原则

在概要设计阶段,根据需求阶段的调研结果,我整理了系统界面设计的基本原则。因为在代码开发阶段,很多时候界面的具体制作是由开发人员直接写代码,因此必须确定一定的原则和规范,以保证系统界面的统一。

一般适用原则

·简单明了原则:用户的操作要尽可能以最直接最形象最易于理解的方式呈现在用户面前。对操作接口,直接点击高于右键操作,文字表示高于图标示意,尽可能的符合用户对类似系统的识别习惯。

·方便使用原则:符合用户习惯为方便使用的第一原则。其它还包括,实现目标功能的最少操作数原则,鼠标最短距离移动原则等。

·用户导向原则:为了方便用户尽快熟悉系统,简化操作,应该尽可能的提供向导性质的操作流程。

·实时帮助原则:用户需要能随时响应问题的用户帮助。

·提供高级自定义功能:为熟悉计算机及软件系统的高级用户设置自定义功能,可以对已经确定的常规操作以及系统的方方面面进行符合自身习惯的自定义设置。包括常规操作、界面排版、界面样式等种种自定义。

·界面色彩要求:计算机屏幕的发光成像和普通视觉成像有很大的不同,应该注意这种差别作出恰当的色彩搭配。对于需用户长时间使用的系统,应当使用户在较长时间使用后不至于过于感到视觉疲劳为宜。例如轻松的淡彩为主配色,灰色系为主配色等等。切忌色彩过多,花哨艳丽,严重妨碍用户视觉交互。

·界面平面版式要求:系统样式排版整齐划一,尽可能划分不同的功能区域于固定位置,方便用户导航使用;排版不宜过于密集,避免产生疲劳感。

B/S构架适用原则

·页面最小:由于Web的网络特性,尽可能减小单页面加载量,降低图片文件大小和数量,加快加载速度,方便用户体验。

·屏幕适应:Web界面需要适应不同用户屏幕大小。

·浏览器兼容:需要适应不同浏览器浏览效果,虽然目前可不考虑不同浏览器差别,但仍需考虑IE浏览器版本差异带来的客户端不同效果。

·最少垂直滚动:尽可能减少垂直方向滚动,尽可能不超过两屏。

·禁止水平滚动:由于将导致非常恶劣的客户体验,尽可能禁止浏览器水平滚动操作。

·避免隐藏(右键)操作:浏览器的右键操作不符合用户体验习惯,尽可能避免。

本系统应用原则

·瘦客户端要求:由于客户应用环境配置大多较低,除服务器可单独配置较灵活外,应该保证瘦客户端,使用户容易使用。例如尽量不要使用复杂的JS脚本和HTC组件,不要在客户端使用IE整合XML/XSLT等等。

·大数据量表格的水平扩展要求:本系统中存在大数据量的列表,需要较大的交互界面支持,为避免水平滚动,应尽可能获取大的屏幕水平空间。

·桌面面板导航简化操作:为了实现方便简捷的用户操作,应该保证用户绝大多数操作可通过首页桌面面板的导航来实现。

·用户自适应定义:提供较多的可订制功能,尤其对桌面面板提供强大的定制功能;使用户能够将最常用的功能定义到桌面面板,每次登录即可直接使用,简化用户操作。

·用户常用操作记录定义:对某些需定义操作的功能如查询、搜索等,提供系统自动记忆和客户定制功能,系统可自动记忆用户前1~3次操作,或者用户可自定义操作记录,方便以后使用。

·大数据量表格的水平扩展要求:本系统中存在大数据量的列表,需要较大的交互界面支持,为避免水平滚动,应尽可能获取大的屏幕水平空间。

4.系统分析

在概要设计过程中,界面设计人员需要浏览需求分析报告,了解用户的工作流程,和整个系统功能,再根据这些原始需求功能,归纳整理分析,并针对用户交互设计需要,提出意见,参与系统设计。

其中包括对原始功能的分类归纳,提出系统交互需要的新功能,对用户功能实现的优先级进行定义等等。

例如,提出用户自定义快捷面板功能,常用操作自动记录功能等,需要在概要设计时尽早提出,以方便作好系统规划。

另外,需要对整个系统中的常见功能有比较清晰的了解,归纳整个系统界面交互中常见的交互形式,例如在本系统中就包括列表、查询、搜索、填写表单、项目分解、项目选择、审批、报告等等;只有清晰的了解整个系统需求,才能较好的把握整个界面设计的统一性。当然,这也和界面设计人员的经验有很大关系。

4.主界面设计

设计主界面,确定系统基本风格,是概要设计中的工作之一。首页主界面的主要实现功能是导航,它要达到的目的,是尽可能使用户仅通过首页面板就可以完成所有常规任务。

该主界面包含以下部分

用户信息区域 显示当前用户信息




用户导航区域
用户页面导航,收藏功能可以将当前功能页面收藏到快捷功能面板




用户导航功能树
用户页面导航,收藏功能可以将当前功能页面收藏到快捷功能面板




功能树隐藏
可水平扩展页面空间

  


桌面面板用户帮助导航
用户登录时可根据用户类型,自动加载相关使用帮助或导航。




主任务通知区域
通知用户系统业务流程中的待办事宜;通知用户办公系统相关信息。




用户快捷面板
为了能方便快捷的访问系统功能,避免每次访问树形菜单较深级次的繁琐操作,用户可将通过导航栏中的收藏按钮,将当前页面收藏到该面板中;该面板出现在所有业务页面,用户可以随时访问自己定义的功能页面。该导航在首页以面板形式出现,在其他页面以下拉菜单形式出现。




用户自定义功能区域 用户可将相关查询搜索等功能定义到首页面板,例如:最新完成报告察看、报告搜索、检验流程察看等等

5.典型界面

以下是系统中几个比较典型的界面模型。



在整个系统界面的设计过程中,需要注意整个系统的统一,设计风格要一致,界面中的交互元素,从色彩、样式到排版方式、具体位置都要具备延续性,这样才能使用户尽快习惯整个系统操作。

6.典型交互模式

界面交互中,根据功能不同,有不同的交互方式。应该尽量提取抽象,尽可能减少交互模式的种类,或者把交互方式尽可能设计的类似,以方便用户快速熟悉系统。

下面列举3个系统中比较典型的交互模式,供大家参考。


单项选择




多项选择




项目分解(GIF动画 4桢)

7.Demo开发

Demo是详细设计阶段的重要成果之一,在对系统进行详细的分析设计之后,开发出界面Demo原型,主要作用是提供给合作客户,在基本功能、系统组成和易用性上进行测试。

本系统的Demo主要包括界面的设计制作,和部分客户端表现层脚本的开发。为了在后面的实际业务开发中尽可能获得重用,Demo的制作在页面规范、CSS样式定义和JS脚本编写方面都严格遵循了系统开发规范,并在以后的代码编写工作中严格执行。

本系统整个Demo包括大约50个页面,耗时月3周。

在后续的开发过程中,仍然要严格控制整个开发过程,保证整个系统界面的统一,并随时维护更新系统界面的设计。

Macromedia提供的usability tips on Flash site

Based on recommendations from top Macromedia Flash designers, developers, and usability experts we’ve collected the top ten tips for creating usable Macromedia Flash sites.

These tips are just a start and we will continue to provide more usability research, studies and articles.

1. Remember User Goals
Users typically come to a site with a goal in mind. Each link and click should meet their expectations and lead them toward their goal. When streaming your site, have key navigation links appear first, in case the user wants to get to another area in the site. Emulating common GUI elements will increase usability.
2. Remember Site Goals
Site design should reflect business or client needs, effectively communicating the main message and promoting the brand. Yet site goals are best achieved by respecting the user experience, so site structure should reflect user needs, quickly leading the user to their goal and avoiding company or regional jargon.
3. Avoid Unnecessary Intros
While intro animations are exciting, they often delay the user’s access to the information they seek. Always offer users either a Skip Intro command or alternative access to your home page. On their second visit to your home page, skip the intro animation altogether (use a client-side JavaScript cookie to accomplish this) then on the destination page give the option of returning to the animation.
4. Provide Logical Navigation and Interactivity
· Keep the user oriented: Display the previous location and guide users to their next one. Remind users where they’ve been by programming links to change color after being visited.
· Give users an easy exit from each major section of the site and an easy return to their starting point.
· Clearly indicate each link’s destination. Keep navigation structures and nomenclature visible, rather than hiding them until the user has triggered an event (such as a mouse over).
· Make sure your buttons have well-defined hit areas.
· Display primary site navigational elements first by using the streaming capabilities of Macromedia Flash.
· Support back button navigation. To do this using built-in browser forward and back navigation, separate Flash movies into logical chunks and place them on individual HTML pages. Alternatively, set up the movie to include a Flash-based Back Button that the user can use to return to a frame or scene that represents a logical previous page.
5. Design for Consistency
Consistency in user interface is the best way to improve your site’s performance. Reusing architecture elements, design elements, and naming conventions frees the user’s attention for your message while they navigate to their goal, and it also aids site maintenance. You can use Smart Clips to reuse interactive elements throughout the site, and have words and images from initial navigation links reappear on destination pages.
6. Don’t Overuse Animation
Avoid unnecessary animations. The best animations reinforce the site’s goals, tell a story, or aid in navigation. Repeated animations on text-heavy pages distract the eye from the message of the page.
7. Use Sound Sparingly
Sound should enhance your site but not be indispensable. For example, use sound to indicate that the user has just triggered an event. Always provide on, off, and volume control on screen, and remember that sound significantly increases file size. When you do use sound, Macromedia Flash will compress music into small MP3 files and even stream it.
8. Target Low-Bandwidth Users
The smaller the download, the better. The initial screen download should be no more than 40k, including all Macromedia Flash files, HTML, and images. To reduce download time, use smaller vector-based images (unless the image is a complex bitmap, in which case it’s better left as a bitmap file), and use the Load Movie action only when the user specifically requests a file. If a wait is unavoidable, provide a load time sequence with a progress indicator, and have navigation load in the first 5 seconds whenever possible.
9. Design for Accessibility
Make your content available to all users, including those with disabilities. Highly descriptive Alternate Tags allow your content to be interpreted by assistive technology. The magnifying Smart Clip for zoom is another easy-to-use Macromedia Flash feature that allows more users to see your content. For an in-depth discussion about making Macromedia Flash content accessible, see the Macromedia Flash Accessibility site.
10. Test for Usability
Have someone with fresh eyes test drive your site to make sure it accomplishes both user goals and site goals. Even compact Macromedia Flash animations can delay users from reaching their goal, so use Macromedia Flash’s built-in Bandwidth Profiler (located in the View menu in Test Movie mode)to analyze how well your site will perform over various bandwidths. Re-test the site each time you make even small changes. Make sure your site testers match the demographic of your site’s anticipated audience—especially if the anticipated audience includes users at various levels of comfort with site navigation.