Dart: const コンストラクタの挙動
September 12, 2022
Flutter で UUID のパッケージを使っているときに疑問に感じたことがありました。
- uuid | Dart Package
- https://pub.dev/packages/uuid
それがこんな場面です。
import 'package:uuid/uuid.dart';
void main() {
var myId = const Uuid().v4();
/*
myId を使って処理をする
*/
}
ここで思ったことが Uuid()
に const
をつけることができるが、const
はコンパイル時定数のはずだから、コンパイル後の myId
の値は常に同じになってしまうのでは?というものです。
結論から書くと、ここで const
をつけても実行時に異なる UUID が生成されます。そのため const
をつけて良いものでした。
この結論を確認する過程で const
の意味の理解が深まったため、ここに記録しておきます。
パッケージの中身を確認する #
まずパッケージの中身を覗いてみました。
https://github.com/Daegalus/dart-uuid/blob/master/lib/uuid.dart
コードから今回関係するところだけ抜き出すと以下です。
class Uuid {
const Uuid({this.options});
String v4({Map<String, dynamic>? options}) {}
}
UUID クラスは const
コンストラクタを持っており(先程のコードで const
がつけられるため当然ですが)、そして String
を返す v4
というメソッドを持っています。
試してみる #
上記を再現するために次のコードを作りました。
main.dart
import 'dart:math';
class MyNumber {
const MyNumber();
String generate() {
return Random().nextDouble().toString();
}
}
void main() {
var value1 = const MyNumber().generate();
var value2 = const MyNumber().generate();
print('value1: $value1');
print('value2: $value2');
}
実行すると、異なる ID が生成されていることが確認できます。
dart run main.dart
>> value1: 0.6285126838021444
>> value2: 0.30805691422589065
事前にコンパイルして実行してみる #
結果は変わらないはずですが、事前にコンパイルしてから実行した結果も確認してみます。
- 参考
- dart compile | Dart
- https://dart.dev/tools/dart-compile
コンパイルします。
dart compile exe main.dart
その後実行します。やはり異なる ID が生成されていることが確認できます。
./main.exe
>> value1: 0.20123072181999224
>> value2: 0.8177948189102009
もう少し試してみる #
では、これを実行するとどうなるでしょうか?
import 'dart:math';
class MyNumber {
const MyNumber();
String generate() {
return Random().nextDouble().toString();
}
}
void main() {
var myNumber1 = const MyNumber();
var myNumber2 = const MyNumber();
var value1 = myNumber1.generate();
var value2 = myNumber2.generate();
print('value1: $value1');
print('value2: $value2');
print('Same Instance? ${myNumber1 == myNumber2}');
}
結果はこのようになります。生成される ID は異なったものですが MyNumber
インスタンスは同じものになっています。
dart run main.dart
>> value1: 0.6635094141767709
>> value2: 0.44454233593829273
>> Same Instance? true
逆に const
を外すと…
import 'dart:math';
class MyNumber {
const MyNumber();
String generate() {
return Random().nextDouble().toString();
}
}
void main() {
var myNumber1 = MyNumber(); // Before: const MyNumber();
var myNumber2 = MyNumber(); // Before: const MyNumber();
var value1 = myNumber1.generate();
var value2 = myNumber2.generate();
print('value1: $value1');
print('value2: $value2');
print('Same Instance? ${myNumber1 == myNumber2}');
}
インスタンスも異なったものになります。
dart run main.dart
>> value1: 0.5566858718089395
>> value2: 0.4242468509827739
>> Same Instance? false
まとめ #
ここまで見て分かることは const
はそのオブジェクト自身を定数化はするが、そのオブジェクトが持っているメソッドが返す結果までは定数化しない、ということです。
自分で手を動かしながら確認すると理解が深まりますね。