Coming from ActionScript and learning Dart is easy. Both languages are class-based, single inheritance, object-oriented languages with C-style syntax. In many cases the syntax is identical or similar, often the Dart syntax is a little shorter and looks less verbose. As a bonus the Dart IDE is based on Eclipsed (but still light weight) and therefore familiar to many ActionScript developers. The Editor helps to write your code by providing autocomplete suggestions, refactoring, code navigation and many other handy tools you are used too. Launch your application directly from the Editor and set breakpoints to debug your code. Now take a look at the list below to learn how to map ActionScript code to Dart code.
public class Spaceship extends Sprite { // fields, constructors, functions }
class Spaceship extends Sprite { // fields, constructors, methods }
var i:int = 1; var s:String = 'hello world'; var n:Number = 3.14; var b:Boolean = true; // Warning: variable 'x' has no type declaration var x; var p = new Point(1, 2);
int i = 1; String s = 'hello world'; num n = 3.14; bool b = true; // No warning because Dart is dynamically typed. var x; var p = new Point(1, 2);
public var name:String; private var _text:String; internal var _code:String; // there is no match for the 'protected' modifier.
String name; // public String _text; // private (see comment below) String _code; // internal (see comment below) // The underscore convention is the access modifier! // The field or method is accessible everywhere in the // current library, but hidden to other libraries.
public function echo(text:String):String { return text; } private function foo(i:int, s:String):void { }
String echo(String text) { return text; } void _foo(int i, String s) { }
public class Sample { public function Sample(i:int, s:String) { // constructor code } } public class Point { public var x:int, y:int; public function Point(x:int, y:int) { this.x = x; this.y = y; } }
class Sample { Sample(int i, String s) { // constructor code } } class Point { int x, y; Point(this.x, this.y); // Automatic field initialization. } // Dart also supports 'named' and 'factory' constructors. // http://www.dartlang.org/docs/language-tour
private var _name:String; public function get name():String { return _name; } public function set name(value:String): void { _name = value; }
String _name; String get name { return _name; } set name(String value) { _name = value; }
public interface ISelectable { function select(var filter:String):void; } // A class implements interfaces. public class Table implements ISelectable { public function select(var filter:String):void { // ... } }
abstract class Selectable { void select(String filter); } // A class implements other classes' interfaces. class Table implements Selectable { void select(String filter) { // ... } }
var o:Object = "hello"; if (o is String) { var u:String = String(o).toUpperCase(); trace(u); }
var o = "hello"; if (o is String) { String u = (o as String).toUpperCase(); print(u); }
var a:Array = new Array(); var b:Array = [1, 2, 3]; var v:Vector.<String> = new Vector.<String>(); v.push('hello'); v.push('world');
var a = new List(); var b = [1, 2, 3]; var v = new List<String>(); v.add('hello'); v.add('world');
var q:Array = new Array(); q.push('hello'); q.push('world'); var f:String = q.shift(); var l:String = q.pop();
var q = new Queue(); // or use: new Queue<String>(); q.add('hello'); q.add('world'); var f = q.removeFirst(); var l = q.removeLast();
var m1:Object = new Object(); m1.name1 = 'Susan'; m1.name2 = 'Michael'; var m2:Object = {name1 : 'Susan', name2 : 'Michael'}; delete m2.name2; var m3:Dictionary = new Dictionary(); m3[0] = new Point(0, 0); m3[1] = new Point(1, 1); delete m3[1];
var m1 = new Map(); // or use: new Map<String, String>(); m1['name1'] = 'Susan'; m1['name2'] = 'Michael'; var m2 = {'name1' : 'Susan', 'name2' : 'Michael'}; m2.remove('name2'); var m3 = new Map<int, Point>(); m3[0] = new Point(0, 0); m3[1] = new Point(1, 1); m3.remove(1);
// A set is a collection without duplicates. // ActionScript has no built-in support for sets. // //
var s = new Set(); // or use: new Set<String>(); s.add('hello'); s.add('world'); s.add('hello'); // will not be added to avoid duplicates.
for(var i:int = 1; i < 10; i++) { trace(i); }
for(int i = 1; i < 10; i++) { print(i); }
var words:Array = ['this', 'is', 'sparta!']; for each(var word:String in words) { trace(word); }
var words = ['this', 'is', 'sparta!']; for(var word in words) { print(word); }
var i:int = 0; while(i < 10) { i++; } var j:int = 0; do { j++; } while(j < 10);
int i = 0; while(i < 10) { i++; } int j = 0; do { j++; } while(j < 10);
var data:Object = {name1 : 'Susan', name2 : 'Michael'}; for(var key:String in data) { var value:String = data[key]; }
var data = {'name1' : 'Susan', 'name2' : 'Michael'}; for (var key in data.keys) { var value = data[key]; }
// All mathematical operations are static member fields // and functions of the 'Math' class. // //
// All mathematical operations are static top level constants // and functions of the 'dart:math' library. import 'dart:math';
var p:Number = Math.PI; var e:Number = Math.E; var s:Number = Math.SQRT2;
var p = PI; var e = E; var s = SQRT2;
var s:Number = Math.sin(Math.PI / 2); var c:Number = Math.cos(Math.PI / 3); var t:Number = Math.tan(Math.PI / 4);
var s = sin(PI / 2); var c = cos(PI / 3); var t = tan(PI / 4);
var r:Number = Math.random();
var random = new Random(); var r = random.nextDouble();
var a:Number = Math.abs(-3.14); var c:Number = Math.ceil(15.54); var f:Number = Math.floor(27.17); var r:Number = Math.round(35.22);
var a = (-3.14).abs(); var c = (15.54).ceil(); var f = (27.17).floor(); var r = (35.22).round();
var i:int = parseInt('12'); var n:Number = parseFloat('27.55');
var i = int.parse('12'); var n = double.parse('27.55');
// ActionScript uses function scoping. public function foo():void { // No warning, variable 'i' is hoisted. trace (i); for(var i:int = 0; i < 10; i++) trace(3 * i); // Warning: Duplicate variable definition. for(var i:int = 0; i < 10; i++) trace(5 * i); }
// Dart uses block scoping. void foo() { // Error: cannot resolve 'i'. print (i); for(int i = 0; i < 10; i++) print(3 * i); // No warning, variable 'i' isn't used in this scope for(int i = 0; i < 10; i++) print(5 * i); }
// The following code prints: 5, 5, 5, 5, 5 var callbacks:Array = new Array(); for(var i:int = 0; i < 5; i++) { callbacks.push(function():void { trace(i); }); } for each(var callback:Function in callbacks) { callback(); }
// The following code prints: 0, 1, 2, 3, 4 var callbacks = new List(); for(int i = 0; i < 5; i++) { callbacks.add(() { print(i); }); } for (var callback in callbacks) { callback(); }
// ActionScript uses a dynamic binding for 'this'. // The function 'Bar.test' will print 'Michael'. public class Foo { public var name:String = 'Susan'; public function printNameFunction():Function { return function():void { trace(this.name); }; } } public class Bar { public var name:String = 'Michael'; public var func:Function; public function test():void { this.func = new Foo().printNameFunction(); this.func(); // prints 'Michael' which is problematic! } }
// Dart uses a lexical binding for 'this'. // The function 'Bar.test' will print 'Susan'. class Foo { String name = 'Susan'; Function printNameFunction() { return () { print(this.name); }; } } class Bar { String name = 'Michael'; Function func; void test() { this.func = new Foo().printNameFunction(); this.func(); // prints 'Susan' which is correct! } }
public function foo(text:String):void { try { if (text == null) throw new ArgumentError("Oh no!"); } catch(ae:ArgumentError) { // catch ArgumentErrors } catch(e:Error) { // catch everything else } finally { // always run this code. } }
void foo(String text) { try { if (text == null) throw new ArgumentError("Oh no!"); } on ArgumentError catch(ae) { // catch ArgumentErrors } catch(e) { // catch everything else } finally { // always run this code. } }
// Positional optional parameters public function foo(s:String = null, b:Boolean = false):void { // Parameter 'b': ActionScript does not support optional // parameters without default values. } // Named optional parameters // ActionScript does not support named optional parameters.
// Positional optional parameters void foo([String s = null, bool b]) { if (b == null) { // Parameter 'b' was not provided. } } // Named optional parameters void bar({String s:null, bool b:false}):void { }
public function get name():String { return _name; } public function calc(value:int):int { return 2 * value; } var func:Function = function(text:String):void { trace(text.toUpperCase()); };
String get name() => _name; int calc(int value) => 2 * value; var func = (String text) => print(text.toUpperCase());
// this feature is not available in ActionScript, // therefore you write something like this: var sprite:Sprite = new Sprite(); sprite.x = 100; sprite.y = 150; sprite.addEventListener(MouseEvent.CLICK, onMouseClick); stage.addChild(sprite);
// Dart offers so called method cascades, it is // a shorter way to write code like this: var sprite = new Sprite() ..x = 100 ..y = 150 ..addEventListener(MouseEvent.CLICK, onMouseClick) ..addTo(stage);
trace('hello world');
print('hello world');
public function hello(first:String, last:String):String { return 'Hello ' + first + ' ' + last; }
String hello(String first, String last) { return 'Hello $first $last'; }
var esc:String = "Hi!\\n\\nNice to meet you!\\n"; // ActionScript does not support raw Strings.
var esc = "Hi!\\n\\nNice to meet you!\\n"; var raw = r"Hi!\n\nNice to meet you!\n";
// ActionScript supports the RexExp class and literal. var pattern1:RegExp = new RegExp("^\\d+$", ""); var pattern2:RegExp = /^\d+$/; var match:Array = pattern1.exec("42"); trace(match[0]); // 42
// Dart only supports the RexExp class. var pattern1 = new RegExp(r"^\d+$"); var match = pattern1.firstMatch("42"); print(match.group(0)); // 42
if (ExternalInterface.available) { ExternalInterface.call("updateHtml", 1, 2, 3); }
updateHtml(1, 2, 3);
// Flash Display List objects var bd:BitmapData = new BitmapData(20, 20, false, 0xFF00FF); var b:Bitmap = new Bitmap(bd); b.rotation = 45; var sprite:Sprite = new Sprite(); sprite.addChild(b); sprite.scaleX = 0.25; sprite.scaleY = 0.50; sprite.addEventListener(MouseEvent.CLICK, onMouseClick); // Flash audio playback var sound:Sound = new Embedded.CoolSound(); var soundChannel:SoundChannel = s.play();
// HTML5 Display List objects var bd = new BitmapData(20, 20, false, 0xFF00FF); var b = new Bitmap(bd); b.rotation = 45 * PI / 180; var sprite = new Sprite(); sprite.addChild(b); sprite.scaleX = 0.25; sprite.scaleY = 0.50; sprite.addEventListener(MouseEvent.CLICK, onMouseClick); // HTML5 audio playback var sound = resource.getSound("CoolSound"); var soundChannel = s.play();
var xml:XML = <persons> <person name='Susan'/> <person name='Michael'/> </persons>; var xmlList:XMLList = xml.elements('person');
var xml = XML.parse(''' <persons> <person name='Susan'/> <person name='Michael'/> </persons> '''; var xmlList = xml.queryAll('person');
var body:b2Body; var bodyDef:b2BodyDef; var boxShape:b2PolygonShape; var circleShape:b2CircleShape;
Body body; BodyDef bodyDef; PolygonShape boxShape; CircleShape circleShape;
import flash.display.*; import com.hurlant.crypto.hash.SHA1;
import 'package:stagexl/stagexl.dart'; import 'dart:crypto' show SHA1; // only SHA1 class is visible import 'dart:html' as html; // Alias, use 'html.window...'