index
id: program-language-dart title: Dart description: Dartにまとめたセクション tags:
- program
- language
Dart
Overview
Dartは、Flutterのプログラミング言語です。Googleが開発しており、以下の特徴がある。
- シンプルでモダンな構文 JavaScriptやJavaに似ており、学習が比較的容易。
- JIT(Just-In-Time)コンパイルとAOT(Ahead-Of-Time)コンパイル 開発中はJITで素早く動作確認ができ、リリース時にはAOTコンパイルされて高速なネイティブコードが生成される。
- 多様な用途 DartはFlutterのために使われることが多いですが、サーバーサイドやWebフロントエンド開発にも対応している。
SwiftやKotlin, Javaと同じように静的型付け言語、クラスベースのオブジェクト指向言語。
モジュール管理
Dartでは1つのDartファイルをライブラリと呼ぶ。
Dartにはprivateやpublicといった可視性をコントロールするキーワードはない。
デフォルトの振る舞いがpublicに相当し、クラスや関数はimport命令によってライブラリの外からもアクセスできる。
クラス名や関数名を_(アンダーバー)ではじめるとprivateとして扱われ、外部からアクセスできなくなる。
Pub.dev
DartおよびFlutterのパッケージ管理のための公式リポジトリサイト。
Dart言語仕様
Dart3が最新。
Dart3からはパターンや、クラス修飾子などが登場している。
Dart3からは全てのコードがnull安全になった。
またRecordやパターンマッチングなどの新機能が追加された。
変数
// 変数の型を宣言する部分をDartでは型注釈と呼ぶ
int age = 0;
Dartには型推論の機能がある、型注釈を省略し代わりに var と記述すると変数の方を推論されることができる。
定数
finalのほか、constという修飾子でも定数を宣言できる。
List(配列)
配列に相当する順序付きコレクションには、DartではListクラスが用意されている。
Listには可変長と固定長の2種類が存在する。
Set(集合)
順序が保持されない、要素が重複しないコレクションとしてSetクラスが用意されている。
Map(連想配列)
連想配列や辞書に相当する key-value ペアとして Map クラスが用意されている。
他の言語と同様にキーは重複しない。
例外の型
DartにはError型とException型があり、それぞれthrowキーワードで例外としてスローできる。
Error型はプログラムの失敗によりスローされるものとされている。間違った関数の使い方や無効な引数が渡された場合など、プログラム上の問題に使用され、呼び出し元で捕捉する必要のないもの。
一方、Exception型は捕捉されることを目的にしたクラスで、エラーに関する情報を持たせるべきとされている。
Dartは以上2つのタイプのほかに任意のオブジェクトを例外としてスローできるが、製品レベルのコードでは推奨されていません。
アサーション
プログラムの開発中に思わぬバグが潜んでいないかチェックする機能。
Flutterではdebugビルドのときにだけassert文が処理されます。その特徴を利用し、debugビルドのときだけ実行したい処理を記述することが可能。
関数
Dartの関数はトップレベルに定義でき、Javaなどとは違い必ずしもクラスに属している必要はない。
引数
引数の宣言方法には、省略可能引数と名前付き引数という2つのユニークな仕様がある。
- 省略可能引数
[]で囲った引数は省略して呼び出せるようになる。省略可能引数は省略されるとnullが渡される。- 省略可能引数はデフォルト値を与えることができる。デフォルト値を与えると、省略可能引数も非null許容型にできる。
- 名前付き引数
- デフォルトでは省略可能として扱われる。
- 必須にする場合は
requiredキーワードを与える。
関数の省略記法
関数が1つの式からなる場合はアロー演算子を使用した省略記法が利用できる。
// 引数を2倍にして返す関数
int doubleValue(int x) {
return x * 2;
}
// 上の関数を省略記法で宣言
int doubleValue(int x) => x * 2;
第一級関数と匿名関数
Dartは第一級関数をサポートした言語。
関数を変数に代入したり、引数に受け取ったりできる。
Dartの匿名関数はクロージャーの性質を持つ。
クラス
Dartはクラスベースのオブジェクト指向言語。
すべてのオブジェクトはクラスのインスタンスであり、null以外のすべてのクラスは Object クラスのサブクラスです。
アクセス修飾子
DartできるDartいがpublicに相当し、クラスや関数はimport命令によってライブラリの外からもアクセスできる。
クラス名や関数名を_(アンダーバー)ではじめるとprivateとして扱われ、外部からアクセスできなくなる。
ゲッタとセッタ
すべてのインスタンス変数は暗黙的にゲッタを持つ。
final修飾子のないインスタンス変数は暗黙的にセッタを持つ。
コンストラクタ
Dartには色々コンストラクタがある。
- constantコンストラクタ
- 名前付きコンストラクタ
- factoryコンストラクタ
コンストラクタを記述しなければ引数なしのデフォルトコンストラクタが提供される。
クラス修飾子
クラス修飾子はクラスやミックスインに付与し、インスタンス化や継承に制限を与えます。
クラス修飾子の一覧。
- abstract
- base
- final
- interface-
- sealed
- mixin
インターフェース
Dartではすべてのクラスは暗黙的にインターフェースが定義されている。
そのクラスのすべての関数とインスタンスメンバを持ったインターフェースになる。
mixin(クラスに機能を追加する)
Dartは多重継承を許可していないが、それに似た言語仕様としてmixin(ミックスイン)がある。
ミックスインはクラスのようにメソッドやフィールドを宣言できる。
クラスとの違いは以下となる。
- インスタンス化できないこと
- extendsキーワードを使って他のクラスから継承できないこと
- コンストラクタを宣言できないこと
Enum
Dartの列挙型はフィールドやメソッド、constantコンストラクタを持った高機能なEnumも宣言できる。
通常のクラスに似た構文だが、いくつかの条件がある。
- 1つ以上のインスタンスすべてが冒頭で宣言されていなくてはならない
- インスタンス変数はfinalでなければならない(mixinで追加されるものも同様)
- コンストラクタはconstantコンストラクタまたはfactoryコンストラクタが宣言可能
- 他のクラスを継承できない
- index、hashCode、==演算子をオーバーライドできない
- valuesという名前のメンバを宣言できない
非同期処理
Future 型と Stream 型スレッドのようなしくみのアイソレートについて解説する。
Future型(フューチャー)
Futureは時間の概念として「未来」や「将来」を指す。
Futureクラスは async, await キーワードと組み合わせることで同期的なコードのように記述できる。
例外発生時に返す代替の値がある場合は then メソッドの引数 onError で処理する方法がある。
Stream型
非同期に連続した値を扱うStream型。
Zone
DartにはZoneという非同期処理のコンテキストを管理するしくみがある。
その機能のひとつに非同期処理で捕捉されなかった例外のハンドリングがある。
ただし、FlutterのエラーハンドリングはZoneではなく前述のPlatformDispatcherを使うことが一般的。
実際はすべてのDartコードはZoneで実行される(main関数は暗黙的にデフォルトZoneで実行される)
アイソレート(isolate)
アイソレート(isolate)の意味は分離する・独立させる。
アイソレートはスレッドやプロセスのような仕組み。
- 専用のヒープメモリを持つ
- 専用の単一のスレッドを持ち、イベントループを実行する
- アイソレート間でメモリの共有はできない。
すべてのDartプログラムはアイソレートの中で実行される。
通常、自動的にメインアイソレートが起動し、その中でプログラムが実行されるので意識することはない。
Flutterアプリとアイソレート
Flutterアプリを作る上でアイソレートを意識することはほとんどない。
メインアイソレートが自動的に起動し、その中でDartプログラムが実行されるから。
アプリでよく実装される時間のかかる処理として、HTTP通信やファイルのI/Oが挙げられる。
これらはOSなどDartコード外で実行され(その間Dartのアイソレートは他のイベントを処理可能)、完了するとDartが再開される。
そのためアプリがフリーズするようなことは起こらない。