はじめに
Dartの基礎文法を学んだので記事にしたいと思います。
開発環境
Dart SDK 2.10.0
型推論
Dartは型を推論できます。
型が決まらないことを明示するためにdynamic型があります。SwiftのAny型みたいなイメージですね。
変数
変数のデフォルト値はnullです。
int i; // i is null
finalキーワードをつけると変更不可になります。
final str1 = "型推論なし";
final String str2 = "型推論あり";
constキーワードをつけるとコンパイル定数となります。
コンパイル定数とは、その定数を利用している箇所がコンパイル時に低数値に書き換わる定数のことです。
finalはプログラム実行時に初期化され、constはコンパイル時に初期化されます。
Built-in型
Built-in型とは、最初から用意されている型のことです。
DartのBuilt-in型は下記の通りです。
- int, double
- String
- bool
- List
- Set
- Map
- Runes
- Symbol
int, double
intは整数、doubleは浮動小数点です。
intとdoubleのどちらかが入る場合は、numで宣言できます。
final int i = 10;
final double d = 3.14;
final num n1 = 10;
final num n2 = 3.14;
String
文字列型です。シングルクオートダブルクオートどちらもでも生成でき、**${}**でテンプレートリテラルを使用できます。
final String str1 = 'aiueo';
final String str2 = 'str is :${str1} ';
print(str2); // str is :aiueo
また、**'''**にすると複数行の文字列を生成できます。
final String str3 = '''
一行目
二行目
''';
print(str3);
rをシングルクォーテーションもしくはダブルクォーテーションの前につけるとraw文字列になります。
final String rawStr = r'アイウエオ\nかきくけこ';
print(rawStr); // アイウエオ\nかきくけこ
bool
真偽値です。trueとfalseどちらもコンパイル定数です。
List
コレクションクラスです。値の追加、代入は下記の通りです。
List<int> list = [];
list.add(10);
list.add(20);
list[1] = 21;
print(list); // [10, 21]
初期化方法は下記の通りです。
List<int> list1 = [];
var list2 = <int>[];
var list3 = List<int>();
複数このリストを初期化したい場合はこのようになります。
var list = new List.generate(10, (i)=> i);
print(list); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Set
Setは値が一意なコレクションクラスです。SetクラスはLinkedHashSetクラスがデフォルト実装になっているので、順序を保持しています。
初期化は下記のようになります。
Set<int> s1 = {};
Set s2 = {};
値が一意になるので、同じ要素を追加した場合は重複しません。
Set<int> s1 = {};
s1.add(1);
s1.add(1);
s1.add(2);
print(s1); // {1, 2}
Map
Mapはkey-valueの連想配列です。
Mapクラスのデフォルト実装は、LinkedHashクラスです。
Map map = Map<String, int>();
map['a'] = 100;
map['b'] = 200;
print(map); // {a: 100, b: 200}
Runes
Runesは文字列内で32ビットUnicode値を表現するためのクラスです。
Dartの文字列はUTF-16コード単位の並びであるので、32ビットのUnicode値を文字列内で表現するにはRuneクラスを使用します。
final String clapping = '\u{1f44f}';
print(clapping);
print(clapping.codeUnits);
print(clapping.runes.toList());
Runes input = new Runes(
'\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(new String.fromCharCodes(input));
Symbol
Symbolは名前つき引数を指定する場合などに使います。
var function1 = (String first, {String second, String third}) {
print(first + second + third); // abc
};
Function.apply(function1, ["a"], {#second: "b", #third: "c"});
アクセス修飾子
Dartにはprivate、publicなどの可視性のキーワードはありません。
クラス名、変数名、関数名が**_(アンスコ)**で始まる場合はプライベートを意味しています。
class _PrivateClass { // private class
int _i; // private property
void _privateFunc() { // private function
}
}
関数
基本的な形は下記のようになります。
戻り値の型 関数名(引数の型 引数名) {
return 戻り値;
}
下記は具体的な関数の定義と呼び出しです。
void main() {
sampleFunction("サンプル"); // sample サンプル
}
void sampleFunction(String str) {
print('sample ${str}');
}
また下記のようにシンタックスシュガーを用いて、**=>**を使って書くこともできます。
bool isEnable(int i) => i == 1;
名前付き引数
下記のように**{}**で囲った引数は呼び出し側で引数名を指定することになります。
またこの引数は任意指定となります。
void main() {
sampleFunction(argument1: 10, argument2: "hoge"); // 10 hoge
sampleFunction(); // null null
}
void sampleFunction({int argument1, String argument2}) {
print(argument1);
print(argument2);
}
@requiredアノテーションをつけると必須引数になります。
void main() {
sampleFunction(argument1: 10, argument2: "hoge"); // 10 hoge
sampleFunction(); // 呼び出せない
}
void sampleFunction({@required int argument1, @required String argument2}) {
print(argument1);
print(argument2);
}
オプショナルパラメーター
引数に**[]**をつけるとオプショナルの引数になり、非必須となります。
void main() {
sampleFunction(10); // 10 null
sampleFunction(10, "aiueo"); // 10 aiueo
}
void sampleFunction(int argument1, [String argument2]) {
print(argument1);
print(argument2);
}
クロージャ
クロージャは下記のように書きます。
void main() {
final add1 = closure(2);
print(add1(10)); // 12
}
Function closure(int addNumber) {
return (int i) => i + addNumber;
}
クラス
下記に、フィールド、コンストラクタ、ゲッター、セッター、メソッドを定義したサンプルのクラスを定義します。
void main() {
final SampleClass sampleClass = SampleClass("けんたろう", 10);
sampleClass.message = "よろしくお願いいたします。";
sampleClass.hello(); // 私の名前はけんたろうです。 歳は10才です。 よろしくお願いいたします。
}
class SampleClass {
// フィールド
final String name;
final int age;
String _message;
// コンストラクタ
SampleClass(this.name, this.age);
// ゲッター
String get message => this._message;
// セッター
set message(String message) => this._message = '私の名前は${this.name}です。 歳は${this.age}才です。 ${message}';
// メソッド
void hello() {
print(this._message);
}
}
Enum
DartのEnumの定義は下記のように書きます。
enum Color { red, green, blue }
各値にはindexプロパティがあり、宣言順の値が取得できます。
void main() {
print(Color.red.index); // 0
}
valuesプロパティを使用すると、Enumで定義した全ての値を取得できます。
void main() {
print(Color.values); // [Color.red, Color.green, Color.blue]
}
switch文で条件分けするときには、全ての値を条件に入れないと警告が出ます。
その代わりdefaultキーワードが不要になります。
void main() {
final Color color = Color.red;
switch (color) {
case Color.red:
print("red"); // red
break;
case Color.green:
print("green");
break;
case Color.blue:
print("blue");
break;
}
}
typedef
typedefを使用すると、関数型に別の名前をつけることができます。
typedef Typedef = String Function(int i);
void main() {
final Typedef t = (int i) => 'argument: ${i}';
print(t(10)); // argument: 10
}