実践Flutter

Flutterでスマホを中心にアプリ制作していきます。

実践Dart:演算子

はじめに

本記事ではDartの演算子についてまとめていきます。

基本的には一般的なプログラミング言語で用いられるものとほぼ違いがありません。型キャスト・型チェック系の演算子で書き方が違うのでここはチェックしておいて下さい。格好いい表記でお気に入りです。スマートキャストも要チェックです。

演算子のなかで一番のお気に入りは「??=」ですね。「+=」や「-=」は太古の昔からの言い伝えレベルですが、この記法が「??」演算子と組合わさると格好よくてちょっと感動しました。





数値計算演算子

数値計算関連演算子は以下の通りです:

シンボル 意味
+ 加算 1+2 //3
- 減算 2-1 //1
* 乗算 2*3 //6
/ 除算 3/2 //1.5
~/ 整数除算 3~/2 //1
% 剰余 3%2 //1

代入系演算子

代入関連演算子は以下の通りです:

シンボル 意味
= 代入 a=1 //aに1代入
+= 加算代入 a+=2 //aに2を加える
-= 減算代入 a-=3 //aから3を減じる
*= 乗算代入 a*=4 //aに4を掛ける
/= 除算代入 a/=5 //aを5で割る
??= ヌルならば代入 x ??= obj //xがnullならばobjを代入
++ 1増加 a++ //aに1を加える
-- 1減少 a-- //aから1を減じる

ここで++演算子と--演算子は、変数の前につけるか、後ろにつけるかで式としての評価値が変わります。C言語からの伝統ですが一応おさらいしておくと:

int a = 1;
print(++a);   //2
print(a);   //2
  
int b = 1;
print(b++);   //1
print(b);   //2

上記の++aは、先にa=a+1が行われて、その後に式全体の評価が行われるのでaが2になり、++aの全体評価も2になります。

一方b++は、先に式全体の評価が行われ、その後でb=b+1が実行されるので、b++の評価は1、bは2になります。

「x+=1」は「x = x +1」の短縮表記なわけですが「x ??= obj」が同様に「x = x ?? obj」の短縮表記になっています。これってJavaなど他言語でよくある次の形:

if(x == null){
  x = obj;
}

この処理を:

x ??= obj;

と書けるというわけです。「??」演算子のデザインはエレガントですよね。

関係演算子

等号、不等号関連演算子は以下の通りです:

シンボル 意味
== 等しい a == b
!= 等しくない a != b
> 大きい a > b
< 小さい a < b
>= 以上 a >= b
<= 以下 a <= b

2つのオブジェクトの比較はJavaなどのequals()メソッドではなく、==演算子で行われます。このため必要に応じて==演算子をオーバーライドします。

==演算子のときはアドレス比較(identicalかどうかの判定)のみを行う言語仕様も多いですが、Dartでは一般にいうequals()メソッドの処理のように、==演算表記で中身の比較で同一性を判定するスタイルです。

型演算子

型チェックに関する演算子は以下の通りです:

シンボル 意味
as 型キャスト a as String //Stringに型キャスト
is 型チェック a is String //aがStringならば真
is! 型チェック a is! String //aがStringでないなら真
if(a is Car){
  (a as Car).name = "Prius";
}

上はa の型がCarであればCarにキャストした上でメンバ変数にアクセスするというコードですが、下記のように実際は型チェック後のif文の分岐のなかではキャストをする必要はありません。これをスマートキャストと言います。

if(a is Car){
  a.name = "Prius";  //キャストなしでCar型としてアクセス可能
}

論理演算子

論理演算子は一般的な他のプログラミング言語と同様です。

シンボル 意味
! 否定 !a //aが真ならば偽
&& 論理積 a && b //aかつbが真ならば真
論理和 a ‖ b //aまたはbが真ならば真

論理積a&&bはaとbが両方真のときに真となります。となると最初にaを評価して結果が偽であった場合、この時点でa&&bの評価は偽で確定します。このとき後ろの式bの評価は行われません。このことには注意です。

同様にして論理和a||bはaあるいはbが真のときに真となります。このとき最初にaを評価して結果が真であった場合、この時点でa||bの評価は真で確定します。そうなると式bの評価は行われません。

少し人工的ですが、例えば下記のコード:

var a = 0;
var b = 0;
  
if((a=1)==1 || ((b=1)==1)){
  print(a);  //1
  print(b);  //0
}

論理積の式をifの条件として与えています。「(a=1)==1」はa=1がaに1を代入、そして「a=1」の評価値は1となります。なので「(a=1)==1」は真です。このときifの条件は真で確定して、論理和の後段の((b=1)==1)は評価されず、bに1は代入されません。

なので上記の結果print(b)の方の出力は0になります。

おわりに

単純な演算子は他のプログラミング言語とそう変わりがありませんでしたね。ただ昔からの細い伝統のルールがあったりしますので、念の為基本的なところはチェックしておいて下さい。

またなるべく短く簡潔な表記を推奨するDartとしては、ここでは触れませんが演算子のオーバーロードにも積極的です。equalsも==演算子のオーバーロードで定義する流儀ですし。

通常のアプリ開発であまり必要がないかもしれませんが、チャンスが有れば使っていきたいですね。


f:id:linkedsort:20211106012232j:plain