この記事を読むのに必要な時間は約 24 分です。
この記事ではDart の基礎文法をチートシートとしてまとめています。
DartPad で動きを確認しよう
基礎文法について確認する前にDartPadをご存知でしょうか?
Web上で簡単にDart コードを実行できるため簡単なデバッグや文法の確認に最適です。
僕も頻繁に利用しております。
本ページのコードもDart Padで実行しながら動きを確認すると効果的かと思います!
DarPad のリンクはこちら
hello world
void は返り値なし。
main() 関数がflutter のエントリーポイント。
print() でコンソール表示。
void main(){ //void は替え値 print('hello'); }
データ型、変数宣言
Dartのデータ型はデフォルトでnull を代入できないnull非許容型。
var は型変更不可、dynamicは後で型変更可。
final は変数宣言時に値確定、const はコンパイル時に値確定。
void main(){ int a =null; //エラー : 全ての型はデフォルトでnull非許容型 int a = 1; // 整数 double b = 2.4; // 実数 String name = "Kurage"; // 文字列 bool isMan = true; // 論理値 // 型推論 var msg = "hello"; // 最初の代入時に型確定。ここではString msg = "thanks"; // エラー; 後から値変更不可 dynamic c = "morning"; // String型に型推論 c = "good night"; // 値の変更可 c = 24; // Int型に変更 print(c); // 24 }
null許容型
? マークをつけてnull を許容できる。
null 許容型には! マークでnull が入らないことを確定するかnull 時の処理を書く。
??= :null なら値を代入。
式 ?? 式 :左辺がnull なら右辺の値を代入、左辺がnull でなければ左辺を代入。
main(){ String? name = 'Jane'; // null 許容型 String? address = null; // nullの代入可能 int? a; // わざわざnullを代入しなくても初期値はnullに自動設定 a??= 3 ;// a がnull なら3 を代入 a??= 5; //a はnull でないので3 のまま print(a); // print 3 print(1 ?? 3); // print 1 print(null ?? 12); // print 12 //myObject?.somePeoperty (myObject != null) ? myObject.someProperty : null //myObject!.somePeoperty ! は例外を投げるのでよっぽどnullでないことが確定していない限り使わない }
型変換 文字列と数値
(変更したい値).toString() :int ,double → String。
変更後の型.parse(変更したい値) :String → int, double, DataTime。
main() { print(1.runtimeType); // データ型を調べる int print(1.toString() is String); // データ型を調べる true print(1.toString().runtimeType); // int→String print(3.1415.toStringAsFixed(3).runtimeType); // double→String 少数4桁目を四捨五入 print(int.parse('2022').runtimeType); // String→int print(double.parse('2.4').runtimeType); // String→double print(DateTime.parse('2022-01-30 10:28:40').runtimeType); // String→DateTime }
List []
要素重複可な配列。
ドキュメントはこちら。
main() { var list1 = [1,2,3,4]; print(list1); // [1,2,3,4] print(list1[1]); // 2 // 空のList List<int> list2 = []; var list3 = <int>[]; list2.add(5); // 末尾に5を追加 list2.add(7); list2[1] = 10; print(list2); // [5,10] print(list1.length); // 4 print(list1.first); // 1 print(list1.last); // 4 print(list1.isEmpty); // false print(list1.reversed); // [4,3,2,1] list1.addAll(list2); print(list1); // addや addAll などのメソッドはvoid を返すため print(list.addAll(list2)); はエラーになる }
Set {}
要素の重複不可な配列。
ドキュメントはこちら。
main() { var set1 = {1,2,3,4}; set1.add(5); set1.add(1); // 重複するため追加されない print(set1); print(set1.isNotEmpty); // true print(set1.contains(1)); // true print(set1.elementAt(1)); // index 1 に入っている 要素をとる 2 print(set1.join()); // 文字列として連結 12345 Set<int> set2 = {5,6,7}; print(set2.map((e) => e*2)); // 各要素に処理を行う {10.12.14} mapは遅延関数 set2.forEach((e) =>print(e)); // 各要素に処理を行う 5 6 7 var setCleared = set1.clear; print(setCleared); }
Listを連結させる
spread 演算子… を使うとList を複製可能。
Map でも同様の連結処理が可能。
main() { List msg1 = ['Welcome']; List msg2 = ['to']; List msg3 = ['magoblo']; //以下の結果は全て同じ [Welcome, to, magoblo] var newList = msg1 + msg2 + msg3; print(newList); var newList2 = [...msg1, ...msg2, ...msg3]; print(newList2); var newList3 = [msg1, msg2, msg3].expand((x) => x).toList(); print(newList3); }
Map {key:value}
keyとvalue の関連を要素にもつ配列。
ドキュメントはこちら。
main() { var map1 = {1:"Bianca", 2:"Flora"}; map1[3] = "Depora"; print(map1); // {1:"Bianca", 2:"Flora" , 3:"Depora"} var map2 = {}; Map<String,int> map3 = {}; map3["Papas"] = 1; // addではなく要素を指定して追加 map3["Sancho"] = 2; print(map3); // {"Papas":1, "Sancho":2} }
型変換 ListとMap
List→Mapへの変更。
//Map<String> → List<Person> main() { final persons = {'Telly': 23, 'Iru': 27, 'Ruka': 25}; final list = persons.entries.map((e) => Person(e.key, e.value)).toList(); print(list); // Person のインスタンスをListとして格納 } class Person { Person(this.name, this.age); String name; int age; }
Map→Listへの変更。
main() { final persons = <Person>[] ..add(Person('Telly', 18)) ..add(Person('Iru', 12)) ..add(Person('Ruka', 12)); final map = {}; persons.forEach((person) => map[person.name] = person.age); print(map); // {Telly: 18, Iru: 12, Ruka: 12} } class Person { Person(this.name, this.age); String name; int age; }
関数
戻り値の型 関数名 (仮引数の型 仮引数名) { return 戻り値; }で宣言。
関数名 (仮引数名: 実引数);で呼び出し。
main() { print(messageFunc(from:"クラゲ",msg:"ぱあ")); } String messageFunc({required String from, required String msg}) { var result = '$fromからのメッセージ 「$msg」'; return result; }
無名関数
匿名関数や無名関数といって関数名を指定しない書き方もあります。
(仮引数の型 仮引数名) {return 戻り値; }
アロー関数=> は {} と全く同じ意味。式が短い時に使用。
戻り値の型 関数名() => 実行したい処理;
void main() { var greeting = (name) { return 'Hello, ${name}!'; }; // この関数は以下の式と等価 // var greeting(name) => return 'Hello, ${name}!'; print(greeting('Dart')); print(greeting is Function); }
引数
引数の指定には通常のものに加えて、任意引数を指定できるPositional引数 []とNamed引数 {}がある。
間違えやすい項目なので下記に詳しくまとめています。
//通常 void normalParams(int id, String name){ print($id, $name); } main(){ normalParams(1, "bob"); // console 1,bob normalParams(1); // エラー } //Positional void positionalParams(int id, [String name = "you"]){ print("$id, $name"); } main(){ positionalParams(1, "bob"); // console 1,bob positionalParams(1); // console 1,you } //Named void namedParams(int id, {String name = "you"}){ print("$id, $name"); } main(){ namedParams(1, name: "bob"); // console 1,bob namedParams(1); // console 1,you }
カスケード記号
カスケード記号(..) をつけることで同じ式へのアクセスを省略できる。
querySelector('#confirm') ?..text = 'Confirm' ..classes.add('important') ..onClick.listen((e) => window.alert('Confirmed!')); // is equal to var button = querySelector('#confirm'); button?.text = 'Confirm'; button?.classes.add('important'); button?.onClick.listen((e) => window.alert('Confirmed!'));
String 内での式の扱い
String 内では${式}で扱い。
main(){ print('${3 + 2}'); print("word".toUpperCase()); }
クラス
クラスを使用する際はインスタンスを作成する。
インスタンス作成の際、コンストラクタによって値が代入されてイニシャライズ(初期化)される。
コンストラクタはthis. を使うことで代入を省略可能。
Named 引数を使って必須引数を指定できる。
class MyColor { int red; int green; int blue; // this を使うことで res- MyColor(this.red, this.green, this.blue); //コンストラクタ //これは下記を簡略化したもの /*MyColor(int red, int green, int blue) { this.red = red; this.green = green; this.blue = blue;* }*/ } void main(){ final color = MyColor(80, 80, 128); // インスタンス color print(color.red); // 80 } // with Named 引数 class MyColor { ... MyColor({required this.red, required this.green, required this.blue}); } final color = MyColor(red: 80, green: 80, blue: 80);
名前付きコンストラクタ
名前付きコンストラクタで複数のコンストラクタを指定可能。
class Point { double x, y; Point(this.x, this.y); //コンストラクタ Point.origin() // 二つ目のコンストラクタ x, y にすでに値が入っている状態で呼び出せる : x = 0, y = 0; } final myPoint = Point.origin();
factoryコンストラクタ
コンストラクタの前にfactoryをつけることでインスタンスを返すfactoryコンストラクタを定義できる。
`userId`から`user_id`という文字列に変わった際、仮にAlbamクラスを3箇所で使っていたとして、factoryコンストラクタを使っていない場合、3箇所全てのコードを修正する必要が出てきますが、factoryコンストラクタを使っていれば`fromJson`メソッド1箇所の修正で済みます。
class Album { final int userId; final int id; final String title; Album({this.userId, this.id, this.title}); factory Album.fromJson(Map<String, dynamic> json) { return Album( userId: json['userId'], id: json['id'], title: json['title'], ); } }
static修飾子
static修飾子を使えば、クラスのプロパティ/メソッドをインスタンス化せずに使用可能。
class Car{ static int doors = 4; static void drive(){ print('I am driving, Hyahhooo'); } } void main() { print(Car.doors); //4 static を使っていないとインスタンスを作成して、インスタンス.doors としなければいけない Car.drive(); //I am driving, Hyahhooo }
abstractクラス
継承されることを前提として、処理内容を記述しないメソッド(抽象メソッド)を含むクラス。
抽象クラス単体ではインスタンス化することはできない。
抽象クラスで定義する抽象メソッドには処理内容を記述できない。
abstract class Shape { // 抽象クラス double getArea(); // 抽象メソッド } // 抽象クラスを継承 class Rectangle extends Shape { double width = 0; double height = 0; Rectangle(this.width, this.height); // 抽象メソッドを実装 double getArea() { return this.width * this.height; } } void main() { var rect = Rectangle(3, 4); print('四角形の面積は${rect.getArea()}㎠'); }
オーバーライド
オーバーライドとはスーパークラスで定義しているメソッドを、同じ名前でサブクラスで再定義すること。
スーパークラスで定義したメソッドと目的は同じであるが、処理が異なるメソッドを定義する場合に使用。
@overrideを使用して、意図的にメソッドをオーバーライドしていることを示すことができます。
class SmartTelevision extends Television { @override void turnOn() {...} // ··· }
インターフェース
インターフェースにより継承先で親クラスの内容が全て実装されていることが保証できる。
Dartには明示的なインターフェースはない。
代わりに、任意のクラスをインターフェースとして使用可能。
これはすべてのクラスにあらかじめ暗黙的にインターフェースが定義されているため。
// 暗黙的インターフェイスPersonにはgreet()メソッドが含まれています class Person { final String _name; Person(this._name); String greet(String who) => 'Hello, $who. I am $_name.'; } // Personインターフェースの実装 class Impostor implements Person { String get _name => ''; String greet(String who) => 'Hi $who. Do you know who I am?'; } String greetBob(Person person) => person.greet('Bob'); void main() { print(greetBob(Person('Kathy'))); print(greetBob(Impostor())); }
コメント