ActionScript 3 for Java Programmers

Let’s face it: The client has not been a friendly place for Java programmers. Java technology on the client with applets, Swing, and JavaFX has had limited success. JavaScript, despite its name, is almost nothing like the Java language. And Adobe Flash—well, it’s just like JavaScript. Or is it? It might have been the case that Flash was like JavaScript a couple of years ago, but with the advent of ActionScript 3, a lot has changed. And I think you’ll find a lot to like.

First, ActionScript—the programming language for Adobe Flex and Flash—is now strongly typed. It also has first-class object orientation, including classes and interfaces. It has extras that you won’t find in Java—notably, get and set functions for properties and a language extension called ECMAScript for XML (E4X), which turns any XML document into objects that you can reference with dot operators, just like regular objects.

This article takes you through the basics of ActionScript 3 and shows how it compares with the Java environment you’re used to. By the end, you should have given up any preconceptions you may have had about ActionScript and have some interest in playing with it. One of the great things about Flex, Flash, and ActionScript is that they’re available at no cost. Simply download Adobe Flex Builder 3 to get started. Flex Builder, which is a sophisticated integrated development environment (IDE), is not a free application, but the Flex Software Development Kit (SDK) that it uses to build Flash applications is.

A word of warning to language purists out there reading this article: I’m not a language guru, so I might gloss over some language details. I’m also not trying to present everything in ActionScript 3 in this article. If that’s what you’re after, many good books on ActionScript 3 are available. What I can do is give you a feel for the language. Here goes.

Classes and interfaces

Just as with Java, everything is really an object in ActionScript 3. There are a few primitive types like integers, but beyond that everything is an object. Similarly, like Java, there are namespaces and packages, like com.jherrington.animals, which would mean company / jack herrington / animal classes, in this case. You can put classes into the default namespace, but it’s better to control your namespace.

To define a class, you use the class keyword, just as with Java. Here’s an example:

package com.jherrington.animals
{
public class Animal
{
public function Animal()
{
}
}
}

In this case, I'm defining an Animal class with a constructor that currently does nothing.

I can add a few member variables and refine the constructor quite easily, as shown here:

package com.jherrington.animals
{
public class Animal
{
public var name:String = "";

private var age:int = 0;

private function Animal( _name:String, _age:int = 30 )
{
name = _name;
age = _age;
}
}
}

Here, I'm defining that an Animal object has two member variables; name, which is a public string, and age, which is a private integer. (Apparently, animals are shy about their age.) The constructor takes one or two values: either the name alone or the name and an age. You can provide default values for arguments by adding them in the function declaration.

What you notice about this code is that the typing is inverted from Java. In Java, the type comes first; in ActionScript, it comes second. This is because strong typing is an add-on to ActionScript. So to support older, non-typed code, the type comes after the variable name.

Let's extend the example by adding a few methods:

package com.jherrington.animals
{
import flash.geom.Point;

public class Animal
{
public var name:String = "";

private var age:int = 0;

private var location:Point = new Point(0,0);

public function Animal( _name:String, _age:int = 30 )
{
name = _name;
age = _age;
}

public function moveTo( x:int, y:int ) : void {
location.x = x;
location.y = y;
}

public function getLocation( ) : Point {
return location;
}
}
}

As you can see here, I've added another private member variable, location, of type Point, which I've imported from Flash's geometry package. And I've added two methods that work with the location: moveTo, which moves the animal, and getLocation, which returns the current location.

Now, that's kind of the Java way to get and set a value. The ActionScript way to do it is a lot cleaner, as you can see in this code:

package com.jherrington.animals
{
import flash.geom.Point;

public class Animal
{
public var name:String = "";

private var age:int = 0;

private var myLocation:Point = new Point(0,0);

public function Animal( _name:String, _age:int = 30 )
{
name = _name;
age = _age;
}

public function set location( pt:Point ) : void {
myLocation = pt;
}

public function get location( ) : Point {
return myLocation;
}
}
}

Here, I'm using get and set functions that are invoked when the client code gets or sets the value of the member variable location. To the client, the location variable looks just like a regular member variable. But you can set whatever code you like to respond to the member variable setting and handle the get of the variable, as well.

How can you make use of this? You can add an event that is triggered when the location changes. Check that out in this code:

package com.jherrington.animals
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.geom.Point;

public class Animal extends EventDispatcher
{
public var name:String = "";

private var age:int = 0;

private var myLocation:Point = new Point(0,0);

public function Animal( _name:String, _age:int = 30 )

name = _name;
age = _age;
}

public function set location ( pt:Point ) : void {
myLocation = pt;
dispatchEvent( new Event( Event.CHANGE ) );
}

public function get location( ) : Point {
return myLocation;
}
}
}

Now, I'm specifying that the Animal class is an event dispatcher- that is, an object from which clients can listen for events. I then dispatch a new event when the location changes.

Here is the client code that creates an animal, sets itself up to watch for change events, then changes its location:

	var a:Animal = new Animal();
a.addEventListener(Event.CHANGE, function( event:Event ) : void {
trace( "The animal has moved!" );
} );
a.location = new Point( 10, 20 );

This code brings up a trace message when the animal has moved. You can define any type of messages you want in ActionScript. Most of the classes are EventDispatchers and have events for which you can add listeners.

Interfaces

Just like Java, the ActionScript 3 language supports builder interfaces and implementing them with classes. The interface shown below is an example of what we might make from the Animal class:

package com.jherrington.animals
{
import flash.geom.Point;

public interface IAnimal
{
function get name() : String;
function set name( n:String ) : void;

function get location() : Point;
function set location( pt:Point ) : void;
}
}

In this case, I'm defining two member variables for the interface that I can both set and get. Yes, you can define methods and member variables in ActionScript interfaces. How cool is that?

To implement the interface, I've made some changes to the Animal class. You can see that in the code below:

package com.jherrington.animals
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.geom.Point;

public class Animal extends EventDispatcher implements IAnimal
{
private var myName:String = "";

public function get name() : String
{
return myName;
}
public function set name( n:String ) : void
{
myName = n;
dispatchEvent( new Event( Event.CHANGE ) );
}
private var myLocation:Point = new Point(0,0);

public function set location ( pt:Point ) : void {
myLocation = pt;
dispatchEvent( new Event( Event.CHANGE ) );
}

public function get location( ) : Point {
return myLocation;
}

public function Animal( _name:String )
{
name = _name;
}
}
}

Of course, I can add variables and methods specific to this class or implement other interfaces in addition to the IAnimal interface. As with Java, however, I can only inherit from one base class.

Statics and constants

ActionScript 3 supports both constants and static member variables as well as static methods. Constants are easy to define, as you can see in the code below:

		public const MINIMUM_AGE:int = 0;
public const MAXIMUM_AGE:int = 2000;

Constants can be of any type you like, but they have to be defined at compile time. They can also be protected or private if you want to scope them that way.

To demonstrate a static function, I show a factory method in the Animal class:

		public static function buildAnimal( n:String ) : IAnimal {
return new Animal( n );
}

Another way to use static method is in a Singleton pattern. Below is an example of a Singleton factory class for the Animal class:

package com.jherrington.animals
{
public class AnimalFactory
{
private static var _factory:AnimalFactory = new AnimalFactory();

public static function get instance() : AnimalFactory {
return _factory;
}

public function build( n:String ) : Animal {
return new Animal( n );
}
}
}

To invoke it, I use the instance member variable to get the single factory object:

private var b:Animal = AnimalFactory.instance.build( "Russell" );

This uses the Singleton factory object to create a new animal with the name Russell.

Inheritance

To demonstrate inheritance, I show three interfaces and classes. The first interface is the IAnimal class I showed before. The second is the Animal class, and the third is a derived class called Dog that overrides a method.

The interface, IAnimal, is shown below:

	public interface IAnimal
{
function get name() : String;
function set name( n:String ) : void;

function move( x:int, y:int ) : void;
}

I've simplified it a bit by taking it back to just a name member variable and a move() method. The first implementation of the interface is the Animal class:

public class Animal extends EventDispatcher implements IAnimal
{
private var myName:String = "";

public function get name() : String
{
return myName;
}
public function set name( n:String ) : void
{
myName = n;
dispatchEvent( new Event( Event.CHANGE ) );
}

public function Animal( _name:String )
{
name = _name;
}

public virtual function move( x:int, y:int ) : void
{
}
}

Then, the Dog class builds on the Animal class by having its own constructor and an override of the move() method:

public class Dog extends Animal
{
public function Dog(_name:String)
{
super(_name);
}

public override function move( x:int, y:int ) : void
{
trace( 'Moving to '+x+', '+y );
}
}

This is a lot like Java code, so you should feel really at home in implementing your object-oriented designs in ActionScript.

Operators and conditionals

Operators in ActionScript are exactly the same as what you find in Java. Similarly, math and Boolean operators are the same:

	var a:int = 5;
var b:int = 6;
var c:int = a * b;
c *= 10;
var d:Boolean = ( c > 10 );
var e:int = d ? 10 : 20;

These examples show a few of the different operators. The only difference in these examples between ActionScript and Java is the syntax for defining the variables.

Like operators, conditionals work exactly the same between the two languages-for example:

	if ( a > 10 ) {
trace( 'low' );
}
else if ( a > 20 ) {
trace( 'high' );
}
else {
threw new Exception( "Strange value" );
}

shows both the conditional syntax and how you can throw exceptions. Exception handling is exactly the same in Java. You can define your own exception types or just use the standard Exception class.

The try, catch, and finally syntax is shown in the example below:

	try
{
location = new Point( -10, 10 );
}
catch( Exception e )
{
trace( e.toString() );
}
finally
{
location = null;
}

This code tries to set the location and traces out the error if a problem occurs. In any case, the location will be set to null at the end.

Iterators

ActionScript 3 doesn't have strongly typed containers, but it's still easy to work with arrays and hash tables. Here is an example of using a for loop to iterate an array:

	var values:Array = new [ 1, 2, 5 ];
for( var i:int = 0; i < values.length; i++ )
trace( values[i] );

But this isn't really the way you want to iterate an array in ActionScript. The best way is to use the for each syntax, as shown in the next sample:

	var values:Array = new [ 1, 2, 5 ];
for each ( var i:int in values )
trace( i );

This code iterates through each element in the array and sets the value of i to each element along the way.

To create a hash table, you use the basic Object type in ActionScript:

	var params:Object = { first:'Jack', last:'Herrington' };
for( var key:String in params )
trace( key+' = '+params[key] );

ActionScript's origins in JavaScript mean that the base object type is a slots-based container that you can easily use as a hash table.

Regular expressions

Regular expressions are baked right into the base syntax for ActionScript. For example, this code:

	if ( name.search( /jack/i ) )
{
trace('hello jack');
}

performs a simple check on a string.

This code uses a regular expression to perform a split operation:

	var values:String = "1,2,3";
for each( var val:String in values.split(/,/) ) {
trace( val );
}

Whether you should have regular expressions embedded in the core syntax is debatable. The architects of Java obviously thought these expressions should go in an external library. But I think that they are useful enough that they should be integrated as they are in ActionScript.

E4X

XML is used widely enough that ActionScript has support for it built right into the language syntax. If you're an XML junkie, you are going to love this. Check it out:

var myData:XML = <names>
<name>Jack</name>
<name>Oso</name>
<name>Sadie</name>
</names>;
for each ( var name:XML in myData..name ) {
trace( name.toString() );
}

This code defines an XML document, then searches it and prints out all the tags.

This next bit of code also gets <name> tags but only tags that are specified with a type of dog.

var myData:XML = <names>
<name type="person">Jack</name>
<name type="dog">Oso</name>
<name type="dog">Sadie</name>
</names>;
for each ( var name:XML in myData..name.(@type='dog') ) {
trace( name.toString() );
}

The @ syntax is similar to XPath and XSLT. It's used to specify that we are looking at attributes and not XML elements.

E4X is a fantastic addition to the language. It turns XML parsing from a chore into a delight. Web services can even be returned in E4X format for easy parsing.

Conclusion

Adobe has made some extraordinary strides with ActionScript. It's a far more sophisticated language than most people give it credit for. I think you'll find that what Adobe has done is taken some of the lessons learned from what is right and wrong about Java and incorporated them into their development of the ActionScript 3 language. You'll be very happy with the result.

For more information

  • For more on the similarities between ActionScript and Java syntax, read Yakov Fain's article, "Comparing the syntax of Java 5 and ActionScript 3" (JDJ, November 12, 2006).
  • A Java-to-ActionScript converter is available for download from Open Source Flash that allows you to use Java rather than ActionScript to create Flash content.
  • For a list of resources to help you migrate between ActionScript, Flex, Java, and JavaScript development, see RIAdobe's comparison list.
  • Flex.org is your source for all things Adobe Flex.
<script type="text/javascript"> var replyEnabled=true; var forumID=1; var threadID=7878; var previewText='Preview'; var pleaseWait='Please Wait ...'; var reply='Reply'; var postMessage='Post Message'; var errorSubject='Please enter a subject.'; var errorBody='You can not post a blank message. Please type your message and try again.'; var cancel='Cancel'; var goBackOrEdit='Go Back/Edit'; var re='Re:'; var lastMessage=0; var stopWatchText='Stop Watching Thread'; var startWatchText='Watch Thread'; var descending='false'; var ctxPath= ''; var postAddress= ctxPath + '/forum/post!post.action?language=' + 'en'; var postAddWatches= ctxPath + '/forum/watches!add.action'; var postRemoveWatches= ctxPath + '/forum/watches!remove.action'; var loggedIn=false; </script> <script src="http://www.infoq.com/scripts/forum.js?rev=new" type="text/javascript"></script>

4 comments

Reply

bug by scott yuan Posted Aug 25, 2008 9:09 PM <script type="text/javascript" language="javascript"> Event.observe('tooltip_31281', 'mouseover', initializeTooltip); Event.observe('tooltip_31281', 'mouseout', deintializeTooltip); </script>
java to as3 converter on AIR by Mansour Raad Posted Aug 26, 2008 7:35 PM <script type="text/javascript" language="javascript"> Event.observe('tooltip_31382', 'mouseover', initializeTooltip); Event.observe('tooltip_31382', 'mouseout', deintializeTooltip); </script>
Error. by Rodrigo Pereira Fraga Posted Aug 27, 2008 11:35 AM <script type="text/javascript" language="javascript"> Event.observe('tooltip_31485', 'mouseover', initializeTooltip); Event.observe('tooltip_31485', 'mouseout', deintializeTooltip); </script>
Still a long way to go! by Shrihari SC Posted Aug 30, 2008 1:32 PM <script type="text/javascript" language="javascript"> Event.observe('tooltip_31601', 'mouseover', initializeTooltip); Event.observe('tooltip_31601', 'mouseout', deintializeTooltip); </script>
  1. Back to top

    bug

    Aug 25, 2008 9:09 PM by scott yuan

    for each ( var name:XML in myData..name.(@type='dog') ) change to for each ( var name:XML in myData..name.(@type=='dog') )

  2. Back to top

    java to as3 converter on AIR

    Aug 26, 2008 7:35 PM by Mansour Raad

    http://thunderheadxpler.blogspot.com/2007/11/java-to-as3-on-air.html

  3. Back to top

    Error.

    Aug 27, 2008 11:35 AM by Rodrigo Pereira Fraga

    Exception == Erros in AS3. So...
    ...
    throw new Error( "Strange value" );
    ...
    And:
    ..
    catch( e:Error )
    ..
    You didn't test this code.

  4. Back to top

    Still a long way to go!

    Aug 30, 2008 1:32 PM by Shrihari SC

    I guess looking at the commonly-used syntax, Actionscript 3 has tried to bridge Java 6 with Javascript. Riding on the success of Adobe Flex, I think this will definitely improvise, and carve a different niche.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值