Flutterをやっています。Dartは不可欠です。今回は、DartのNull Safeとか言うややこしいけど多分ものすごく良いものだろう仕組みで使われる、!と?について自分的にまとめてみました。
Null Safeとは?
一時期「ぬるぽ」なる言葉が流行りまして、これはプログラムがNullを指した時にでるメッセージ[Null Pointer]から来たものですが、プログラマーはつねにNullと隣り合わせです。それを解決しようとしたのが、Null Safeですね。ここぐらいまでが、私の頭の限界ですので、とっととまとめます。
次の2つがある
2021年9月30日 コメントでご指摘いただきましたので、以下は実行時に変数を変換しているのでは無くコンパイラに知らせているだけだと追記させていただきます。
1. 絶対Nullじゃないことを前提とした変数や返り値
2. Nullかも知れないことを想定した変数や返り値
これらをそれぞれ変換するには
?:1から2へ
!:2から1へ
つまり
1. 絶対Nullじゃないことを前提とした変数や返り値
↑! ↓?
2. Nullかも知れないことを想定した変数や返り値
と言う具合に変換できます。
?について
宣言
Nullかもしれない変数は、型名の後に?つけます。
int? i;
すると、こうなります。
int nullJanaiyo() {
return 1;
}
int? nullKamo() {
return null;
}
main() {
int keppeki = nullJanaiyo(); //OK
int? hoge = nullKamo(); //OK
int keppeki2 = nullKamo(); //Error
int? hoge2 = nullJanaiyo(); //OK
}
判定
?が2つ。変数判定
?が2つ並んでいるのは、左辺をnullかどうか判定しています。次のような場合に用います。
int? hoge = null;
int keppeki = hoge; //Error
int keppeki2 = hoge ?? 1; //OK
print(keppeki2); //1がプリントされる
オブジェクトに?. オブジェクト判定
オブジェクトの右に?.をつけることで、オブジェクトがNullでない場合に、.以降のメソッドを実行できます。オブジェクトがnullなら、メソッドは実行されません。
class ItsMe {
void say() => print("hello");
}
ItsMe nullJanaiyo() {
return ItsMe();
}
ItsMe? nullKamo() {
return null;
}
main() {
ItsMe me = nullJanaiyo();
ItsMe? who = nullKamo();
me.say(); //OK。helloがプリントされる
who.say(); //Error
who?.say(); //OK。何もプリントされない
}
!について
しっかりしなさい!
変数に!
Nullかも知れない変数は、実は!でNullじゃない変数に変換できます。次の3行目です。
int? hoge = null;
print(hoge); //nullがプリントされる
int keppeki = hoge!; //文法は通る
print(keppeki); //Error
このように、Nullかも知れない変数の後に!をつけると、Nullじゃない変数になります。ところがNullじゃないと言ったにも関わらずNullだったために、その後のprint文でエラーとなってしまいます。一方初めからNullかも知れないと言っていたhogeは、エラーになっていません。
関数に!
変数同様、関数も!でNullじゃない関数にできます。
class You {
late Function say;
late Function? hya;
setFunction(func) {
this.say = func;
}
}
main() {
You you = You();
you.setFunction(() => print("Hello"));
you.say(); //OK
you.hya(); //文法Error
you.hya!(); //Error
}
終わりに
以上、自分の理解を深める意味も込めて、ダダダと書いてみました。参考になりましたら幸いです。