late
とは
late
はDart 2.12から追加されたキーワードで、2つのユースケースがあります。
- 遅延初期化
- 宣言後に初期化されるnon-nullable変数の宣言
詳しくは公式Docを参照ください。
活用例
変数宣言時のthis
へのアクセス
late
で修飾した変数は、宣言時にthis
にアクセスできます。
class User {
User({required this.firstName, required this.lastName});
final String firstName;
final String lastName;
late String fullName = '$firstName $lastName'; // ('${this.firstName} ${this.lastName}')
}
不要なこともある高コスト変数の宣言
使用されない場合もある、初期化にコストがかかる変数をlate
で宣言しておくと、その変数が使用されない場合は初期化もされないのでコスト削減できます。
以下の例ではtemperature
が使われない場合、高コストな_readThermometer()
は呼ばれません。
late String temperature = _readThermometer();
Null Safety有効化時のUnit Test
Unit Testを書く時に、setUp()
で各test
の前に変数を初期化するという処理をすることがあると思います。
以下のコードはNull Safety有効化前は正常に動きます。
import 'package:flutter_test/flutter_test.dart';
void main() {
List<Book> books;
BookManager bookManager;
setUp(() {
books = [Book(title: 'A'), Book(title: 'B'), Book(title: 'C')];
bookManager = BookManager(books);
});
group('create', () {
test('BookManager has 4 books after create', () {
bookManager.create(title: 'D');
expect(bookManager.books.length, 4);
});
});
}
しかし、Null Safetyを有効にすると以下のエラーが発生します。
Null Safety有効化前はbooks
やbookManager
は暗黙的にnullableになっていましたが、Null Safetyを有効化後はnon-nullableになるため初期化をしなければならないためです。
The non-nullable local variable 'books' must be assigned before it can be used.
Try giving it an initializer expression, or ensure that it's assigned on every execution path.
------------------------------------------------------------------------------------------------
The non-nullable local variable 'bookManager' must be assigned before it can be used.
Try giving it an initializer expression, or ensure that it's assigned on every execution path.
late
をつけた正常に動くコードは以下のようになります。
これはユースケースの「宣言後に初期化されるnon-nullable変数の宣言」に当たります。
import 'package:flutter_test/flutter_test.dart';
void main() {
late List<Book> books; // lateを追加
late BookManager bookManager; // lateを追加
setUp(() {
books = [Book(title: 'A'), Book(title: 'B'), Book(title: 'C')];
bookManager = BookManager(books);
});
group('create', () {
test('BookManager has 4 books after create', () {
bookManager.create(title: 'D');
expect(bookManager.books.length, 4);
});
});
}