== 演算子と暗黙の型変換

前回の続きです。なぜ "" == foo が true と評価されるのか、まず、暗黙の型変換が行われる際のルールを一つ確認します。

暗黙の型変換の基準

暗黙の型変換が行われる際の基準となる型は、変数に関連付けられた型注釈ではなく、値であるオブジェクト自体の型です。ですので変数の型に注目していても暗黙の型変換の結果は分かりません。

例えば、今回問題になっている例 foo:Object = 0 では、値である 0 の型が暗黙の型変換の基準になります。foo の型ではありません。そのため if 文の条件は文字列とと数値の比較として扱われます。

var foo:Object = 0;
if ("" == foo) { // 実際には "" == 0 が評価される
  trace("foo is null String");
}
 

そうすると、今回のケースでは "" と 0 が等価であるかどうかが評価されていることになります。

== 実行時の暗黙の型変換のルール

さて、文字列と数値を == で評価する際には、「文字列を数値に変換してから比較する」というルールが適用されます。そのため、まず空文字列から数値への変換が行われます。

AS3 では数値表現として扱うことのできない文字列を数値に変換した場合の結果は 0 になります。空文字列も意味の有る数値表現ではありませんから数値に型変換されたときの値は 0 です。すると "" == 0 は 0 == 0 となります。これにより if 文は最終的に true になるわけです。

別の例を見てみましょう。今度は空の配列と空文字列を比較するケースです。

var foo:Object = [];
if ("" == foo) {
  trace("foo は空文字列です");
}
 

こちらのケースも "foo は空文字列です" が表示されます。

ここで適用されたルールは、「文字列と配列を == で評価する場合は配列を文字列に変換してから行う」というものです。空の配列を String 型に変換すると空文字列になるため、上の if 文の条件は "" == "" となり、結果として true になったと考えることができます。

ここまでのまとめ

ここで一旦まとめてみましょう。まず、== 演算子では比較対照のデータ型が異なる場合、暗黙の型変換が行われます。そして、変換のルールは型の組み合わせに応じていくつかのルールの中から選ばれます。

ECMAScript の定義を参照すると == 演算子を実行する前に、適用される暗黙の型変換ルールを決定する 23 ステップ相当の条件チェックが必要であることが分かります。従って == 演算子の結果を正しく予測するには、この 23 ステップを適用した場合に起こりうる全てのケースについて考慮する必要があります。さらに、それぞれのケースについて、「空文字列は 0 に変換される」とか「空の配列は空文字列に変換される」といったルールを全て把握していなければなりません。

これはあまり現実的とはいえませんよね。ということで、ここまでのまとめとしては、

  • == 演算子の結果は信用できない

ということになります。

少し AS3 をかばっておくと、これは ECMAScript に準拠したために起きている状況で、AS3 の設計者がみんなを混乱させてやろうとか思った訳では (決して) ありません。

ともあれ、== を使わずにプログラムを書くのも難しいので、プログラムを記述する側で何らかの対応をすることが必要になります。次はその対応方法を考えてみたいと思います。

コメントする

2014年1月

Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
レンタルサーバー

月別 アーカイブ

Powered by Movable Type 4.261