――― 「Dartってプログラミング言語知ってる?」「知らない」
いきなりこのような見出しで始まりました「Dartで遊んでみようシリーズ」ですが、今日は最初ということで「Dartの紹介」と「『Dartって新しいくせに特徴全然無いよね』とか言われて悲しい」をテーマに書いていこうと思います。
まず、Dartとは何か。 Dartとは、Googleによって2011年に発表された新しいプログラミング言語です。言語のサイトはこちら。 JavaScriptへの変換及び、独自のDartVM上で動作させることにより、ブラウザ上でもデスクトップ上でも実行することが可能です。 規模の大きなwebアプリケーションの開発を楽に行えるようにすることを目的に作られており、JavaScriptの置き換えを狙っているそうです。 クラスベースで単一継承のみの純粋オブジェクト指向の言語であり、構文はJavaによく似ているため学習コストが低いのもウリです。 型システムはOptional Typingであり、型を付けても付けなくても良いというものになっています。 現時点での最新の言語規格は0.10です。 開発環境としてEclipseベースのDartEditorというIDEがリリースされており、環境構築は楽だと思います。
問題・・・ さてここで問題になるのが、他の方にDartについての説明をすると「Dartって新しい言語なのに、目玉機能ないよね」とよく言われることです。 確かに、書いていると凄くJavaっぽい印象を受けるので、あまり新しい言語でプログラムを書いているような感じがしません。 ですが、Dartは細かい点でより書きやすくなっているのです!
ということで、文法面を中心にアピールしてみようと思い、余り見られないような文法を使ったコード片をこさえてみました。
interface HogeInterface default Hoge {
const HogeInterface(String s);
addExclamationFunc();
}
class Foo {
const Foo(this._text);
factory Foo.makeHoge(String s) => const Hoge(s);
String get text() => _text;
final String _text;
}
class Hoge extends Foo implements HogeInterface {
const Hoge(String s)
: super(s);
addExclamationFunc() => () => const Hoge("$text!");
Hoge operator+(Hoge rhs) => const Hoge("${text}${rhs.text}");
String toString() => text;
}
main() {
print(
"${(
const Hoge("cod") +
new Foo.makeHoge("el") +
const HogeInterface ("ogy")
)
.addExclamationFunc()()
.toString()}");
}
無理やり詰めました。
では、コードの頭から読む前に、とりあえずmain関数から追ってみます。 まず見慣れないのは、24行目から31行目までのprintの引数の文字列でしょうか。 $変数名、及び${式}はその時点に計算され、文字列に埋め込まれます。文字列内挿(String interpolation)といいます。 次に、newとconstですね。newはお馴染みのインスタンスの生成ですが、constはコンパイル時定数値の生成となります。
では、一番上に戻り、interfaceから見てみます。 interfaceでは、defaultを指定することによってデフォルトのファクトリを指定することが可能です。 つまり、interfaceの実体化を試みた際に、その指定されたものが実体化されるようになります。 この記法は現時点においてDartのライブラリでよく使われているので、引っかからないように注意が必要です。
次に、一つ目のclass定義を見てみます。 7行目の const Foo がコンパイル時定数用のコンストラクタです。constを付けることによって、そのような指定をしたことになります。 パラメータの this.text ですが、これで直接にメンバの text を初期化することができます。これが地味に便利ですね! また、名前を で始めることによってprivateな扱いになります。 8行目、factory Foo.makeHoge ですが、これは 名前付き の ファクトリコンストラクタとなります。 まず、クラス名 . 任意の名前 と書くことによって、名前付きのコンストラクタが作成されます。複数のコンストラクタを作成したい場合や、コンストラクタの内容を明確にしたい場合に用います。 また、factory指定で、そのクラス以外の型のインスタンスを返すことが可能です。 そのまま後に続く => ですが、この => 式 は { return 式; } とまったく同じ意味となります。 10行目、String get text() => text は getter となります。Dartはgetterやsetterといったアクセッサをサポートします。(余談ですが、アクセッサは構文が変更される可能性があります。) 最後、11行目の final String _text; はいわゆるフィールドです。privateで再代入不可能なString型のフィールドですね。
さて、次のclass定義です。extendsでクラスの継承、implementsでインターフェースの実装を意味します。ここはJavaと同じですね。 16行目のHogeのコンストラクタでは、super を使って基底クラスを初期化しています。(ここで this を用いると別のコンストラクタにリダイレクトすることも可能です) ここでは、地味に初期化子リストを使っていますね。 18行目の addExclamationFunc() => () => const Hoge("$text!"); ですが、これは関数オブジェクトを返しています。 そして、19行目の operator がキモです。Dartは演算子の定義もサポートしています。
等々、駆け足になってしまいましたが、とりあえずこのような地味な改良が多々施されているといった紹介でした。個人的に演算子オーバーロードが楽しいですね。 ジェネリクスやabstructなども一応機能としては入っています。また、言語仕様0.10でようやくキャスト式も導入されました。 まだまだ紹介するものは沢山あるのですが、後々にまわすとしましょう。