2021/12/9 : Dart : Conditional member access ( ?. )について

 

(この記事、というかこのブログ全体で、言葉の定義として

フィールド = プロパティ

です。)

Conditional member access

nullableな変数に対して使うことで実行時エラーを防げる。

//sample_1
void main() {
  P? p1;
  
  int n = p1.y; //←error
  print('$n');
  
}

class P{
  int y=0;
}

 

//result of sample_1
line 4 • The property 'y' can't be unconditionally accessed because the receiver can be 'null'. (view docs)
Try making the access conditional (using '?.') or adding a null check to the target ('!').

sample_1では

「プロパティ’y’は無条件にアクセスできません、なぜならreceiver(参照しようとしているインスタンス、つまりp1のこと)の値がnullになる可能性があるからです。

コンディショナルにアクセスする(‘?.’を使う)か、あるいはターゲット( p1のこと)に対して(‘!’を使って)nullチェックをしてください。」

というエラーメッセージが出る。

実際sample_1ではp1の値はnullなので、p1.yはnull.yということになるが、nullのyフィールドにはアクセスできない。


Conditional member access( ?. )を使ってみる。

//sample_2

void main() {
  P? p1;
  
    //↓Conditional member accessを使う。
  int n = p1?.y;  //←error
  print('$n');
  
}

class P{
  int y=0;
}

 

result of sample_2
line 4 • A value of type 'int?' can't be assigned to a variable of type 'int'. (view docs)
Try changing the type of the variable, or casting the right-hand type to 'int'.

「int?型の値を、int型の変数に代入することはできません。変数(a)の型を(int?に)変更するか、右側の変数を(int?→intに)キャストしてください。」

 

Conditional member access( ?. )は、receiver(p1)が「nullでない」ならフィールドにアクセスする、receiver(p1)がnullなら「p1?.y全体」がnullと評価される、というもの。

(だからreceiver(p1)がnullでも実行時エラーは出ない。)

今回のサンプルで言うと、

=> p1が「nullでない」なら、p1?.yはp1のyフィールドの値

=> p1がnullなら、p1?.yはnull

と評価される。

sampel_2ではp1の値はnull(初期化されていない)なので、p1?.yはnullと評価される。

つまりp1?.yはnullになる可能性があるので、nullable型と認識(判断)される。

しかし、代入先のnはint型(non-nullable型)で宣言されているので上記のコンパイルエラーが出ている。


nをnullable型で宣言する。

//sample_3

void main() {
  P? p1;
  
  //↓nをnullable型で宣言
  int? n = p1?.y;
  print('$n'); //null
  
}

class P{
  int y=0;
}

 

null
(エラー無し)

nをnullble型で宣言すればnullable型の値をnullble型の変数に代入することになるので、sample_2で出ていたエラーは出なくなる。


と言うことで、

//sample3_1

void main() {
  P? p1;
  int? n;

  if(p1 != null){
    n = p1.y;
  }else{
    n = null;
  }
 
  print('$n'); // null
}

class P{
  int y=0;
}

 

//sample3_2

void main() {
  P? p1;
  
  int? n = p1 != null ? p1.y : null;
  
  print('$n'); // null
}

class P{
  int y=0;
}

sample3はsample3_1、sample3_2と同じ意味(同じ結果)となります。

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です