新しいDart Editor(ビルド5549)が公開されています。
ダウンロードはこちらから。
Tutorial: Dart Editor : Dart : Structured web programming
FileビューでDartのライブラリが参照できるようになっています。以前のLibraryビューのように使えるようになりました。
2012年3月21日水曜日
2012年3月18日日曜日
DartiumのWindows版ビルド済みバイナリが公開されています
Dart VMを搭載したWebブラウザDartiumのWindows版ビルド済みバイナリが公開されています。MacOS X版とLinux版のバイナリはすでに公開されていましたが、これでWindowsでも気軽に試せるようになります。
今確認したところでは公式ページの Chromium with the Dart VM からはまだダウンロードできませんが、そのうちダウンロードできるようになるでしょう。現時点ではこちらからダウンロードできます。
http://gsdview.appspot.com/dartium-archive/continuous/
追記
まだおかしいですね。一応実行まではできましたが簡単にクラッシュしてしまいますし、公式ページからダウンロードできるようになるまでもう少し待ったほうがいいかもしれません。
こちらもどうぞ
今確認したところでは公式ページの Chromium with the Dart VM からはまだダウンロードできませんが、そのうちダウンロードできるようになるでしょう。現時点ではこちらからダウンロードできます。
http://gsdview.appspot.com/dartium-archive/continuous/
追記
まだおかしいですね。一応実行まではできましたが簡単にクラッシュしてしまいますし、公式ページからダウンロードできるようになるまでもう少し待ったほうがいいかもしれません。
こちらもどうぞ
2012年3月16日金曜日
新しいDart Editor(ビルド5427)が公開されています
新しいDart Editor(ビルド5427)が公開されています。
ダウンロードはこちらから。
Tutorial: Dart Editor : Dart : Structured web programming
隣り合った文字列の連結ができるようになっています。
そのほかの変更点や詳細はDart News & Updatesの記事を参照して下さい。 New Dart Editor builds supports adjacent string literals
こちらもどうぞ
ダウンロードはこちらから。
Tutorial: Dart Editor : Dart : Structured web programming
隣り合った文字列の連結ができるようになっています。
main() {
String abcdef = 'abc' 'def';
String html = "<p>"
" <em>Hello</em>"
" <i>World</i>"
"</p>";
}
そのほかの変更点や詳細はDart News & Updatesの記事を参照して下さい。 New Dart Editor builds supports adjacent string literals
こちらもどうぞ
2012年3月13日火曜日
Dartにおけるゲッター(get)とセッター(set)
Dartではクラスのメンバーにgetとset(いわゆるゲッターとセッター)を定義することができます。ゲッターとセッターで定義されたメンバーは、あたかもメンバー変数と同じようにアクセスできますが、変数への代入だけではなく、ほかの処理を追加することもできます。
ゲッターとセッターはメソッドと同じような形で、戻り値の方の後にgetあるいはsetを付けます。 ゲッターは仮引数を持たず、適切な値を返します。セッターは適切な仮引数を1つ持ち、値は返しません。 アクセスするときには、メンバー変数へアクセスするときと同じ方法で参照できます。
また、ゲッターとセッターはオーバーライドすることができません。
こちらもどうぞ
ゲッターとセッターはメソッドと同じような形で、戻り値の方の後にgetあるいはsetを付けます。 ゲッターは仮引数を持たず、適切な値を返します。セッターは適切な仮引数を1つ持ち、値は返しません。 アクセスするときには、メンバー変数へアクセスするときと同じ方法で参照できます。
class Line {
Line(this.start, this.end);
int start, end;
int get length() => end - start;
void set length(int len) {
end = start + len;
}
}
main() {
Line line = new Line(1, 3);
// ほかのメンバー変数(line.startなど)と同じ方法で参照できる。
// 出力: (1, 3) : length=2
print('(${line.start}, ${line.end}) : length=${line.length}');
// メンバー変数と同じ方法で代入もできる。
line.length = 5;
// 出力: (1, 6) : length=5
print('(${line.start}, ${line.end}) : length=${line.length}');
}
この例のように同じ名前のゲッターとセッターを1つのクラス内で定義することができます。しかし同じ名前のメンバー変数やメソッドを持つことはできません。
class Line1 {
int length;
int get length() => /* ... */; // エラー!
}
class Line2 {
int length() { /* ... */ }
int get length() => /* ... */ ; // エラー!
}
このような場合には、メンバー変数をプライベートにする(_lengthにする)と良いでしょう。また、ゲッターとセッターはオーバーライドすることができません。
class Line {
int get length() => /* ... */;
String get length() => /* ... */; // エラー!
}
ゲッターとセッターの定義の前にstaticを付けると、静的なゲッターとセッターを定義することもできます。
こちらもどうぞ
2012年3月12日月曜日
Dartで関数型のエイリアスを使う
Dartではtypedefで型のエイリアス(別名)を定義できます。
// 「num型の引数を2つ受け取りbool型の値を返す」関数型のエイリアス
typedef bool Comparator(num, num);
void func(Comparator c) {
// 処理
}
main() {
Comparator c = (a, b) => a > b;
func(c);
}
typedefによって定義されたエイリアスも型ですので、isによる型の判定ができます。
print(c is Comparator); // trueただし現時点では関数型だけに使えます。今後は他の型でも使えるようになるかもしれません。
2012年3月11日日曜日
Dartコードの実行時間を計測する
Dartコードの実行時間を計測するにはStopwatchライブラリが使えます。
こちらもどうぞ
main() {
Stopwatch sw = new Stopwatch.start();
// 計測したい処理
sw.stop();
print('${sw.elapsedInMs()} ms');
}
こちらもどうぞ
プロダクションモードとチェックモード
Dartのコンパイルと実行には、プロダクションモードとチェックモードがあります。夫々次のような特徴があります。
プロダクションモードでは、プログラムの実行を継続できないエラーが発生しない限り、なるべくエラーを無視してそのまま実行を続けようとします。また、できるだけ速く実行するために、型のチェックなども行われません。
一方チェックモードでは、バグの原因と考えられる問題をなるべく早く検出するため、静的な型のチェックだけでなく、動的な方のチェックやassertによるチェックも有効になります。
したがって、開発時はチェックモードを、リリース時はプロダクションモードを使用しましょう。どのVMもデフォルトはプロダクションモードなので、開発時にチェックモードにする意識さえあれば良いはずです。
こちらもどうぞ
| プロダクションモード | チェックモード | |
|---|---|---|
| 静的型 | 無視(Dynamic) | チェック |
| 動的型チェック | なし | あり |
| assert | 無視 | 有効 |
| 優先事項 | 起動時間、実行速度 | 潜在的な問題の検出 |
| デフォルト | V |
プロダクションモードでは、プログラムの実行を継続できないエラーが発生しない限り、なるべくエラーを無視してそのまま実行を続けようとします。また、できるだけ速く実行するために、型のチェックなども行われません。
一方チェックモードでは、バグの原因と考えられる問題をなるべく早く検出するため、静的な型のチェックだけでなく、動的な方のチェックやassertによるチェックも有効になります。
したがって、開発時はチェックモードを、リリース時はプロダクションモードを使用しましょう。どのVMもデフォルトはプロダクションモードなので、開発時にチェックモードにする意識さえあれば良いはずです。
こちらもどうぞ
2012年3月9日金曜日
Dartで文字列を連結する
Dartで文字列を連結するにはいくつ方法があります。
一番単純なものはプラス + によるものです。
さらに、現時点(言語仕様 0.07)ではできませんが、隣接した文字列リテラル同士も連結されるようになるそうです。これはまだ推測ですが、おそらく次のように書けるようになると思います。
Dart Editor ビルド5427からできるようになりました。
こちらもどうぞ
一番単純なものはプラス + によるものです。
String a = "abc" + "def"; // "abcdef"文字列補間を使って次のように書くこともできます。
String a = "abc";
String d = "def";
String ad = "${a}${d}"; // "abcdef"
プラスによる単純な連結で十分な場合はそれで良いと思いますが、文字列補間はたいへん便利な機能なので、ぜひ使っていきたいところです。文字列連結だけではなく、様々な処理を簡単に書くことができます。さらに、現時点(言語仕様 0.07)ではできませんが、隣接した文字列リテラル同士も連結されるようになるそうです。これはまだ推測ですが、おそらく次のように書けるようになると思います。
String a = "abc" "def"; // "abcdef"追記
Dart Editor ビルド5427からできるようになりました。
こちらもどうぞ
2012年3月8日木曜日
新しいDart Editor(ビルド5104)が公開されています
新しいDart Editor(ビルド5104)が公開されています。
ダウンロードはこちらから。
Tutorial: Dart Editor : Dart : Structured web programming
もっとも大きな変更点は、従来のライブラリビューがなくなり、新たにファイルビューが用意されたことです。Dart Editorを起動すると左にファイルビューが表示されます。スクリーンショットはサンプルのclockを開いた状態です。
ひとつ前のバージョン(ビルド4760)では次のようになっていました。
パッと見て2つ気が付きます。
ダウンロードはこちらから。
Tutorial: Dart Editor : Dart : Structured web programming
もっとも大きな変更点は、従来のライブラリビューがなくなり、新たにファイルビューが用意されたことです。Dart Editorを起動すると左にファイルビューが表示されます。スクリーンショットはサンプルのclockを開いた状態です。
ひとつ前のバージョン(ビルド4760)では次のようになっていました。
パッと見て2つ気が付きます。
- 標準のライブラリが表示されないようになった
- Dartライブラリではないもの(ディレクトリや画像ファイルなど)が表示されるようになった
ファイルビューには標準のライブラリが表示されないため、ライブラリビューからそのソースを表示できなくなったのですが、コードから追っていくことは可能です。
開きたいファイルが書かれた #import ディレクティブを右クリックし、メニューから Open Declaration を選択すると、今まで通り指定のライブラリ ファイルが開かれます。
2012年3月7日水曜日
Dartの関数宣言と呼び出し
Dartの関数はJavaやCなどに近い書き方で記述します。
関数の中に式がひとつしかないときは、次のような書き方もできます。この場合、関数の戻り値は式の値になります。
こちらもどうぞ
String greeting(String name) {
String words = 'Hello, ${name}!';
print(words);
return words;
}
return文を通らずに関数を抜けた場合(例外が発生した場合を除く)、エラーにはならずnullが返ります。関数の中に式がひとつしかないときは、次のような書き方もできます。この場合、関数の戻り値は式の値になります。
String greeting(String name) => 'Hello, ${name}!';
無名関数も同じように書くことができます。
main() {
Function greeting1 = (name) { return 'Hello, ${name}!'; };
print(greeting1('world'));
// 書き方が違うだけで同じ。
Function greeting2 = (name) => 'Hello, ${name}!';
print(greeting2('world'));
}
無名関数はコレクションの処理ではよく使われます。サンプルコード
main() {
var even = [1, 2, 3, 4].filter((e) => e % 2 == 0);
even.forEach((e) => print(e)); // 2 4
}
関数を返す関数も書くことができます。クロージャとしての使い方も可能です。サンプルコード
newCounter() {
var i = 0;
return () => ++i;
}
main() {
var c = newCounter();
print(c()); // 1
print(c()); // 2
print(c()); // 3
}
関数には省略可能なパラメーターが指定できます。省略可能なものについてはかっこ [] で囲います。また、省略可能なパラメーターにはデフォルト値が指定できます。省略可能なパラメーターで、デフォルト値がないものについて省略した場合、nullが設定されます。サンプルコード
// 仮引数twoとthreeは省略可能。
void printNumber(int one, [int two, int three = 3]) {
print('${one}, ${two}, ${three}');
}
main() {
printNumber(1, 2, 3); // 1, 2, 3
printNumber(1, 2); // 1, 2, 3
printNumber(1); // 1, null, 3
// デフォルト値がない引数が省略されるとnullになる。
}
ただし、インターフェイスや抽象メソッドではデフォルト値を指定できません。サンプルコード
interface I {
// void greeting([String name = 'world']);
// 上の宣言はエラー。次のようにデフォルト値がなければ問題ない。
void greeting([String name]);
}
class C implements I {
// 抽象メソッドでなければデフォルト値を指定可能。
void greeting([String name = 'world']) {
print('Hello, ${name}!');
}
}
main() {
new C().greeting(); // Hello, world!
}
また、省略可能なパラメーターは名前付きの引数指定に対応します。サンプルコード
void printNumber(int one, [int two, int three]) {
print('${one}, ${two}, ${three}');
}
main() {
printNumber(1, three: 3); // 1, null, 3
}
こちらもどうぞ
2012年3月6日火曜日
Dartでクラスや変数の見え方を制御する
Dartでは、識別子の前にアンダーバー _ をつけると、識別子を定義したライブラリ内でしか見えなくなり、ライブラリの外から参照しようとするとエラーになります。いわゆるプライベートです。
mylib.dart
なお、この機能はライブラリ外から見えなくなるだけで、メンバーをプライベートにしても、同じライブラリ内からは別のクラスからでも参照することができます。
こちらもどうぞ
mylib.dart
#library('my_lib');
class A {
String x;
String _y;
}
#import('mylib.dart');
main() {
A a = new A(); // OK
a.x = 'a'; // OK
a._y = 'a'; // NG
}
メンバー変数だけではなく、メンバー関数や、トップレベルのクラス、関数、変数も同様の方法でプライベートにすることができます。なお、この機能はライブラリ外から見えなくなるだけで、メンバーをプライベートにしても、同じライブラリ内からは別のクラスからでも参照することができます。
#library('my_lib_2');
class A {
String x;
String _y;
}
class _B {}
class Test1 {
void test() {
A a = new A(); // OK
a.x = 'a'; // OK
a._y = 'a'; // OK
_B b = new _B(); // OK
}
}
class Test2 extends A {
void test() {
x = 'a'; // OK
_y = 'a'; // OK
}
}
こちらもどうぞ
Dartのライブラリとスクリプト
Dartではライブラリという単位で構成を管理します。ライブラリ単位でスクリプトにインポートしたり、ライブラリ単位で名前空間を分けたりします。クラスや変数をプライベートにすることで外部から見えなくなりますが、その単位がライブラリでもあります。
ライブラリはファイルの先頭に #library ディレクティブを指定して作成します。
mylib.dart
mysource.dart
こちらもどうぞ
ライブラリはファイルの先頭に #library ディレクティブを指定して作成します。
mylib.dart
#library('my_greeting_lib');
class Greeting {
void hello(String name) => print('Hello, ${name}!');
}
作成したライブラリは別のコードから #import ディレクティブを使ってインポートし、使用します。
#import('mylib.dart');
main() {
Greeting g = new Greeting();
g.hello('world'); // Hello, world!
}
ただしこのままですと、複数のライブラリで同じ名前のクラスが定義されていたときに混乱してしまいます。そこでライブラリをインポートするときにはプレフィックス(接頭子)を指定できます。mylib.dart以外のライブラリをインポートするときに別のプレフィックスを指定すれば、そのライブラリが別のGreetingクラスを定義していたとしても、混乱せずに使い分けることができます。
#import('mylib.dart', prefix:'mylib');
main() {
mylib.Greeting g = new mylib.Greeting();
g.hello('world'); // Hello, world!
}
ライブラリとしてではなく、コードの一部として別のファイルを取り込むには、#source ディレクティブを使用します。ライブラリとして取り込むと取り込んだ側のコードのスコープから見えるようになるだけですが、ソースとして取り込むと取り込んだ側のコードの一部として扱われ、プライベートとして指定していないと取り込んだライブラリの外にも公開されます。mysource.dart
class MySouce {}
mynestedlib.dart
#library('my_nested_lib');
class MyNestedLib {}
mylib.dart
#library('my_lib');
#import('mynestedlib.dart');
#source('mysource.dart');
class Greeting {
void hello() {
new MySource(); // OK
new MyNestedLib(); // OK
}
}
#import('mylib.dart', prefix:'mylib');
main() {
new mylib.Greeting.hello(); // OK
new mylib.MySource(); // OK
new mylib.MyNestedLib(); // NG
}
なお、ライブラリの中でもトップレベルのmain関数を含むものをスクリプトと呼びます。こちらもどうぞ
2012年3月5日月曜日
Dartのコンストラクタ
Dartはクラスベースのオブジェクト指向言語です。この仕組みはJavaなどの他の静的なクラスベースの言語に近いものですが、動的な言語であるDartのコンストラクタには面白い機能があります。
まずは基本的なコンストラクタの書き方です。
コンストラクタを書かなかった場合は
コンストラクタを省略した場合や、コンストラクタの中でメンバー変数を初期化しなかった場合、その変数の値はデフォルトの値(null)になります。
コロンに続く部分はイニシャライザー・リストと呼び、スーパークラスのコンストラクタの呼び出しやメンバーの初期化を行います。C++にあるものとほぼ同じです。ただしメンバーの初期化は、代入と同じで等号 = によって書きます。
ここまで見てきたコンストラクタの他に、名前付きコンストラクタとファクトリー・コンストラクタというものがあります。
名前付きコンストラクタは、異なるパラメータでコンストラクタを呼び出すときに使います。Dartではメソッドのオーバーロードができないため、パラメータの異なるコンストラクタを用意したい場合には、名前付きコンストラクタを使います。
ファクトリー・コンストラクタを作るには、まず通常のコンストラクタに
ファクトリー・コンストラクタは派生クラスのインスタンスを生成することもできます。ファクトリー・コンストラクタを使って、引数に応じて処理方法を変えたハッシュ テーブルの実装を返すなど、柔軟な実装もできます。
なお、インターフェイスにデフォルトのファクトリー・クラスを指定した場合には、インターフェイスにおいてコンストラクタの形式を指定する必要があります。
こちらもどうぞ
まずは基本的なコンストラクタの書き方です。
class Dog {
String name;
// コンストラクタ
Dog(String name) {
this.name = name;
}
}
main() {
Dog afriend = new Dog('Taro');
}
コンストラクタはクラス名と同じ名前のメソッドです。戻り値は書きません。コンストラクタを書かなかった場合は
Dog() : super() {} というコンストラクタがあるものとして扱われます。super() はスーパークラスの引数なしコンストラクタの呼び出しです。コンストラクタを省略した場合や、コンストラクタの中でメンバー変数を初期化しなかった場合、その変数の値はデフォルトの値(null)になります。
コロンに続く部分はイニシャライザー・リストと呼び、スーパークラスのコンストラクタの呼び出しやメンバーの初期化を行います。C++にあるものとほぼ同じです。ただしメンバーの初期化は、代入と同じで等号 = によって書きます。
class Dog {
String name;
Dog(String name) : this.name = name;
}
さらに、コンストラクタの引数をインスタンス変数に代入するというよく行われる処理を、より簡単に書くことができます。class Dog {
String name;
Dog(this.name);
}
この例では、Dogクラスのコンストラクタで引数として受け取った値を、nameフィールドに代入しています。ここまで見てきたコンストラクタの他に、名前付きコンストラクタとファクトリー・コンストラクタというものがあります。
名前付きコンストラクタは、異なるパラメータでコンストラクタを呼び出すときに使います。Dartではメソッドのオーバーロードができないため、パラメータの異なるコンストラクタを用意したい場合には、名前付きコンストラクタを使います。
class Dog {
String name;
int age = 0;
Dog(String this.name);
// 引数なし。
Dog.wild() : name = 'Unknown', age = -1;
// 名前と、年齢を誕生日で指定。
// 年齢の計算方法は大雑把なので参考にしないでください。
Dog.pet(String this.name, Date birth)
: age = new Date.now().difference(birth).inDays ~/ 365;
}
main() {
// "Unknown age=unknown" (-1)
Dog w = new Dog.wild();
// "Taro age=6"
Dog p = new Dog.pet('Taro', new Date(2005, 10, 1, 0, 0, 0, 0));
for (Dog dog in <Dog>[w, p]) {
print('${dog.name} age=${dog.age < 0 ? "unknown" : dog.age}');
}
}
ファクトリー・コンストラクタは、ファクトリー・パターンを実現するものです。インスタンスの生成に関する詳細をファクトリー・メソッドに委譲します。ファクトリー・コンストラクタを作るには、まず通常のコンストラクタに
factory キーワードをつけます。そしてコンストラクタの中でインスタンスを生成し、呼び出し側に返します。例えば次の例のように、生成したオブジェクトをキャッシュしておいて、状況に応じてキャッシュされたインスタンスを返すなどの実装が考えられます。class BinChar {
String c;
// キャッシュ
// バイナリーを表す文字を保持する2つのインスタンスをキャッシュする。
static BinChar zero, one;
// 通常のコンストラクタ
BinChar._internal(String this.c);
// ファクトリー・コンストラクタ
// 初めての呼び出しの時は通常のコンストラクタを呼び出してインスタンスを生成しキャッシュに保存する。
// 2度目以降の呼び出しではキャッシュの値を返す。
factory BinChar(int bin) {
if (bin == 0) {
if (zero == null) {
zero = new BinChar._internal('-');
}
return zero;
} else {
if (one == null) {
one = new BinChar._internal('*');
}
return one;
}
}
}
main() {
// 通常のインスタンスの生成とまったく同じ。
BinChar a = new BinChar(1);
print('1 = ${a.c}');
}
ファクトリー・コンストラクタを使ってインスタンスを生成する場合でも、クライアント側のコードは通常のコンストラクタを使った場合と変わりません。ファクトリー・コンストラクタは派生クラスのインスタンスを生成することもできます。ファクトリー・コンストラクタを使って、引数に応じて処理方法を変えたハッシュ テーブルの実装を返すなど、柔軟な実装もできます。
なお、インターフェイスにデフォルトのファクトリー・クラスを指定した場合には、インターフェイスにおいてコンストラクタの形式を指定する必要があります。
interface Animal default Dog {
Animal(String name); // デフォルトのファクトリー・クラスのコンストラクタを指定する。
}
class Dog implements Animal {
String name;
Dog(String this.name); // インターフェイスのコンストラクタと同じ形式のコンストラクタを用意する。
}
また、定数しか持たないクラスのインスタンスを作るため、constコンストラクタ(定数コンストラクタ)というものもあります。
class Point {
final num x, y;
const Point(this.x, this.y);
}
main() {
Point a = const Point(1, 2);
print('(x, y) = (${a.x}, ${a.y})'); // (x, y) = (1, 2)
}
constコンストラクタでは定数を作るために使います。したがって次のような制約があります。
- constコンストラクタを持つクラスでは、finalではないメンバーを持つことができません。
- constコンストラクタには本体を持つことができませんので、初期化リストなどを用いてメンバー変数の値を初期化することになります。
- constコンストラクタの呼び出しには、コンパイル時定数しか渡すことができません。
こちらもどうぞ
2012年3月4日日曜日
Dart Editorの新しいバージョンが公開されています
Dart Editorの新しいバージョン、ビルド4760が公開されています。
新しい機能は次のとおりです。
ダウンロードはDart Editorのページから。
ただしプロジェクトが開けないなどの問題がいくつかの環境で報告されている(Issue 1962 - dart - DartEditor does not open projects, broken from 4908 to latest DartBuild MacOSX)ようですので、そのような場合は1つ前のバージョンを使うか、より新しいナイトリービルドを使うのが良いでしょう。
新しい機能は次のとおりです。
- Dartiumを起動する機能が向上しました
- コンソールビューでDart VMのスタックトレースにハイパーリンクがつくようになりました
- UIとサンプルが更新されました
- dart:isolateライブラリが登場しました
ダウンロードはDart Editorのページから。
ただしプロジェクトが開けないなどの問題がいくつかの環境で報告されている(Issue 1962 - dart - DartEditor does not open projects, broken from 4908 to latest DartBuild MacOSX)ようですので、そのような場合は1つ前のバージョンを使うか、より新しいナイトリービルドを使うのが良いでしょう。
クラスとインターフェイス
Dart はクラスベースのオブジェクト指向言語です。クラス、そしてインターフェイスという、他のオブジェクト指向言語と似た仕組みを持ちます。
他にも次のような特徴があります。
DartのListでは、デフォルトのファクトリー・クラスとして ListFactory クラスが指定されています。デフォルトのファクトリー・クラスが指定されているインターフェイスは、そのままインスタンスを生成することができます。サンプルコード
こちらもどうぞ
- クラスは他のひとつのクラスを拡張(extends)します。多重継承はできません。
- クラスの定義で extends を省略したときは、Object を拡張することになります。
- クラスは複数のインターフェイスを実装(implements)できます。
- インターフェイスは複数のインターフェイスを拡張(extends)できます。
// 動物インターフェイス
interface Animal {
void cry();
}
// 犬は動物を継承
class Dog implements Animal {
void cry() { print("Bark!"); }
}
// 猫も動物を継承
class Cat implements Animal {
void cry() { print("Mew!"); }
}
// ライオンはネコ科
class Lion extends Cat {
void cry() { print("Roar!"); }
}
// 動物園で吠えます。
void zoo(Animal a) {
a.cry();
}
main() {
zoo(new Dog()); // Bark!
zoo(new Cat()); // Mew!
zoo(new Lion()); // Roar!
}
このあたりの仕組みはJavaとほぼ同じですので、Javaに慣れている人はとっつきやすいと思います。他にも次のような特徴があります。
- クラスは型変数を extends できません。(
class A<T> extends Tということはできない) - インターフェイスはデフォルトのファクトリー・クラスを指定できます。
- インターフェイスには定数の宣言を含むことができます。(
static ABC = "ABC";)
interface Listデフォルトのファクトリー・クラスは default キーワードに続けて指定します。extends Collection default ListFactory { ... }
DartのListでは、デフォルトのファクトリー・クラスとして ListFactory クラスが指定されています。デフォルトのファクトリー・クラスが指定されているインターフェイスは、そのままインスタンスを生成することができます。サンプルコード
main() {
List animals = new List();
animals.add(new Dog());
animals.add(new Cat());
animals.add(new Lion());
for (Animal a in animals) {
a.cry();
}
}
こちらもどうぞ
2012年3月2日金曜日
Dartで変数の型を調べる
Dart において変数の型を調べるには、is 演算子を使います。
var a = 1;
print('a is int: ${a is int}'); // true
型Aが型Bから派生して作られている場合は、A is B は true となります。class B {}
class A extends B {}
main () {
var a = new A();
print('a is B: ${a is B}'); // true
var b = new B();
print('b is A: ${b is A}'); // false
}
Dart におけるすべての型は Object クラスを継承するので、is Object とすると比較対象がどのような型であっても常に true になります。print('1 is Object: ${1 is Object}'); // true
print('"a" is Object: ${"a" is Object}'); // true
対象が null であっても is Object の結果は true です。print('null is Object: ${null is Object}'); // true
したがって、変数がnullかどうかのチェックをするのに is Object は使えません。null と直接比較しましょう。func(var x) {
if (x is Object) { /* たとえxがnullであっても、ここは常に実行される。 */ }
if (x != null) { /* xがnull以外の場合のみ実行される。 */ }
}
Dartをチェックモードで動かす方法
この情報は古くなっています。新しい記事を書きましたのでそちらを参照してください。: Dartをチェックモードで動かす方法(更新版)
Dartの実行モードには、プロダクション モードとチェック モードがあります。プロダクション モードでは、変数の代入などについて型による制限はありませんが、チェック モードでは型のチェックがコンパイル時と実行時に行われます。
開発時はチェック モードで動作させ、製品リリース後はプロダクション モードで動かす、といった使い方が想定されます。
そのため何も指定せずにDartスクリプトを実行するとプロダクション モードで動きます。チェック モードで動かす方法は次のとおりです。
Dartboard の場合
画面左上にあるChecked Modeにチェックを入れます。
dart(Dart VM)の場合
--enable_type_checks フラグを指定します。
frogc( Dart-to-JavaScript compiler)の場合
Dart VMと同じ --enable_type_checks フラグ、または --checked フラグを指定します。
Dartium (Chromium with the Dart VM)の場合
Dartium内蔵のDart VMに渡すフラグは、DART_FLAGS環境変数で指定できます。ここにDart VMと同じフラグを指定します。
Ubuntuの場合は次のようになります。
Dart Editorの場合
スクリプトの実行設定画面の Run in check mode のチェックを入れます。
こちらもどうぞ
Dartの実行モードには、プロダクション モードとチェック モードがあります。プロダクション モードでは、変数の代入などについて型による制限はありませんが、チェック モードでは型のチェックがコンパイル時と実行時に行われます。
開発時はチェック モードで動作させ、製品リリース後はプロダクション モードで動かす、といった使い方が想定されます。
そのため何も指定せずにDartスクリプトを実行するとプロダクション モードで動きます。チェック モードで動かす方法は次のとおりです。
Dartboard の場合
画面左上にあるChecked Modeにチェックを入れます。
dart(Dart VM)の場合
--enable_type_checks フラグを指定します。
$ cat test.dart
main() { int a = 'a'; }
$ dart --enable_type_checks test.dart
'test.dart': Failed type check: line 1 pos 18: type 'OneByteString' is not assignable to type 'int' of 'a'.
0. Function: '::main' url: 'test.dart' line:1 col:18
frogc( Dart-to-JavaScript compiler)の場合
Dart VMと同じ --enable_type_checks フラグ、または --checked フラグを指定します。
$ cat test.dart
main() { int a = 'a'; }
$ frogc --enable_type_checks test.dart
test.dart:1:18: warning: type "dart:core.String" is not assignable to "dart:core.int"
main() { int a = 'a'; }
^^^
Dartium (Chromium with the Dart VM)の場合
Dartium内蔵のDart VMに渡すフラグは、DART_FLAGS環境変数で指定できます。ここにDart VMと同じフラグを指定します。
Ubuntuの場合は次のようになります。
DART_FLAGS='--enable_type_checks' chrome
Dart Editorの場合
スクリプトの実行設定画面の Run in check mode のチェックを入れます。
こちらもどうぞ
Dartium を使ってみる
Dartium は、Dart VM が組み込まれた Chromium です。Chromium は Chrome Webブラウザのオープンソース版です。
Dartium を使えば Dart をWebブラウザ上で試すことができます。現在のところDartiumのLinux版とMacOS X版のバイナリーが公開されていて、Dartの公式サイト内にある Chromium with the Dart VM のページからダウンロードすることができます。Windowsでも自分でビルドすれば動くと思いますし、遠くないうちに提供されるのではないかと思います。
Dartium を起動するとこんなかんじです。
Chromiumとほとんど変わりません。aboutの画面はこんなかんじです。
Dartのサンプルに含まれている dart/samples/hi を表示してみましょう。Dart VMが組み込まれていない通常のChromeですとこうなります。
Dartiumですとこうなります。
Dart言語の部分のコードはこうなっています。
こちらもどうぞ
Dartium を使えば Dart をWebブラウザ上で試すことができます。現在のところDartiumのLinux版とMacOS X版のバイナリーが公開されていて、Dartの公式サイト内にある Chromium with the Dart VM のページからダウンロードすることができます。Windowsでも自分でビルドすれば動くと思いますし、遠くないうちに提供されるのではないかと思います。
Dartium を起動するとこんなかんじです。
Chromiumとほとんど変わりません。aboutの画面はこんなかんじです。
Dartのサンプルに含まれている dart/samples/hi を表示してみましょう。Dart VMが組み込まれていない通常のChromeですとこうなります。
Dartiumですとこうなります。
Dart言語の部分のコードはこうなっています。
#library('hi');
#import('dart:html');
main() {
document.query('#status').innerHTML = 'Hi, Dart';
}
このサンプルから呼び出されている dart.js のコードを見ると、JavaScriptからDartのコードを開始していることがわかります。該当部分を抜粋したものが次のコード片です。if (navigator.webkitStartDart) {
navigator.webkitStartDart();
}
navigator.webkitStartDart() を呼び出すことで、Dartのmain関数が呼び出されるようです。こちらもどうぞ
2012年3月1日木曜日
Dartにおける型とモード
Dartにおいて特定の型を想定せずに変数を定義するには、varキーワードを使います。
varを使って定義した変数は動的な型(厳密にはDynamic型)になり、どのような型のオブジェクトでも代入することができます。初期化のときに設定した値とは別の型でもかまいません。
ここでは代入のみ例に出しましたが、関数の呼出しパラメーターや、関数からの戻り値でも同様です。つまりパラメーターにint型の値を受けとると指定された関数にtrueを渡せますし、戻り値としてint型を返すと指定された関数がList型のオブジェクトを返すことも可能です。
ここまでは普通にDartのコードを実行した時の説明でした。Dartにはこれとは別に、型のチェックを有効にするモードがあります。上で見たような型チェックを行わないモードを「プロダクション モード(production mode)」、型のチェックを行うモードを「チェック モード(checked mode)」と呼びます。
Dartboard では、左上の「Checked Mode」のチェックを入れるとチェック モードになります。
チェック モードの型チェックは、コンパイル時と実行時の両方で行われます。コンパイル時にはコード上で明らかに分かるエラーのみチェックされ、あとは実行時にチェックが行われます。実行時にエラーを検出するとその場で動作は停止します。
プロダクション モードはチェックが行われませんので、プログラムの実行が停止することはありません。もし実行に影響のある問題が起きた場合は、例外が発生します。たとえばある型を想定してメソッドを呼び出したがそのような名前のメソッドは存在しなかったときには、NoSuchMethodException が発生します。
こちらもどうぞ
var a = 1; var b = 'abc';定義の時に初期化を行わない場合、その値はnullになります。
varを使って定義した変数は動的な型(厳密にはDynamic型)になり、どのような型のオブジェクトでも代入することができます。初期化のときに設定した値とは別の型でもかまいません。
var a = 1; a = 'abc'; // 問題なしまたDartには、bool、int、doubleなどのインターフェイスが標準のライブラリ dart:core に用意されています。Dartでは、varを使って定義した変数だけではなく、どんな型を使って定義した変数であっても、すべての型の値が代入できます。つまり次のようなコードでも文法上は問題ないというわけです。
int a = 1; a = true; // intで定義した変数aにboolの値を代入している。 a = new List(); // intで定義した変数aにListのオブジェクトを代入している。 String b = 2; // Stringで定義した変数bを整数2で初期化している。変数aは型intを使って定義されていますが、bool型であるtrueやList型のオブジェクトも問題なく代入できます。つまり変数の定義時にどのような型を指定しても動的な型として扱われ、他のあらゆる型のオブジェクトも代入することができます。
ここでは代入のみ例に出しましたが、関数の呼出しパラメーターや、関数からの戻り値でも同様です。つまりパラメーターにint型の値を受けとると指定された関数にtrueを渡せますし、戻り値としてint型を返すと指定された関数がList型のオブジェクトを返すことも可能です。
ここまでは普通にDartのコードを実行した時の説明でした。Dartにはこれとは別に、型のチェックを有効にするモードがあります。上で見たような型チェックを行わないモードを「プロダクション モード(production mode)」、型のチェックを行うモードを「チェック モード(checked mode)」と呼びます。
int a = 1; a = true; // エラー a = new List(); // エラー String b = 2; // エラー var c = 1; c = true; // 問題なし c = new List(); // 問題なしチェック モードでは、変数を定義したときと別の型の値を代入しようとするとエラーになります。ただしチェック モードでも、var型の変数はどのような型の値を代入してもエラーになりません。
Dartboard では、左上の「Checked Mode」のチェックを入れるとチェック モードになります。
チェック モードの型チェックは、コンパイル時と実行時の両方で行われます。コンパイル時にはコード上で明らかに分かるエラーのみチェックされ、あとは実行時にチェックが行われます。実行時にエラーを検出するとその場で動作は停止します。
プロダクション モードはチェックが行われませんので、プログラムの実行が停止することはありません。もし実行に影響のある問題が起きた場合は、例外が発生します。たとえばある型を想定してメソッドを呼び出したがそのような名前のメソッドは存在しなかったときには、NoSuchMethodException が発生します。
こちらもどうぞ
Dartにおける剰余(モジュロ)
Dart言語では剰余(除算の余り)は % 演算子で計算できます。
とはいえ、ここで例にあげた言語だけでも剰余の符号の扱いはそれぞれ異なりますので、どの言語で書く場合でも剰余の扱いは注意が必要なポイントです。
この動作は実際のDart VMで確認したものです。確認できた限りではDart言語仕様で触れられてない内容ですので、今後変更になるかもしれません。
main() {
print('3 % 2 = ${3 % 2}'); // 3 % 2 = 1
}
これは問題ないと思いますが、負の値を与えたときには注意が必要です。Dartでは剰余の計算結果における符号は、常に正となります。サンプルコードmain() {
print(' 3 % 2 = ${ 3 % 2}'); // 3 % 2 = 1
print('-3 % 2 = ${-3 % 2}'); // -3 % 2 = 1
print(' 3 % -2 = ${ 3 % -2}'); // 3 % -2 = 1
print('-3 % -2 = ${-3 % -2}'); // -3 % -2 = 1
}
これはC/C++やJava、Ruby、Pyhtonなどと異なる動作です。たとえばJavaでは、剰余の符号は割られる数(被除数)の符号と一致します。他の言語の感覚で扱ってしまうと思わぬ動作にはまってしまうかもしれませんので注意してください。とはいえ、ここで例にあげた言語だけでも剰余の符号の扱いはそれぞれ異なりますので、どの言語で書く場合でも剰余の扱いは注意が必要なポイントです。
この動作は実際のDart VMで確認したものです。確認できた限りではDart言語仕様で触れられてない内容ですので、今後変更になるかもしれません。
登録:
コメント (Atom)













