1

宣言された型を自分の番号で取得したいのですが、取得する方法がわかりません。だから私は可能な検出方法でテストを書きました:

logNumber(Number(3.5), "Number");
logNumber(Number(3), "Number");
logNumber(Number(-3), "Number");
logNumber(uint(3), "uint")
logNumber(int(3), "int")
logNumber(int(-3), "int")

function logNumber(value:*, expected:String):void
{
    trace("\n\n\n ");
    trace("** Input value: " + value + "\n** Expected: " + expected + "\n")
    trace("getQualifiedClassName: ", getQualifiedClassName(value) + check(getQualifiedClassName(value), expected));

    switch (value)
    {
        case value as uint:
        {
            trace('as: uint' + check('uint', expected));
            break;
        }
        case value as int:
        {
            trace('as: int' + check('int', expected));
            break;
        }
        case value as Number:
        {
            trace('as: Number' + check('Number', expected));
            break;
        }
    }

    if(value is uint) trace("is: uint" + check('uint', expected));
    else if(value is int) trace("is: int" + check('int', expected));
    else if(value is Number) trace("is: Number" + check('Number', expected));

    trace("describeType name:" + describeType(value).@name + check(describeType(value).@name, expected));

    trace("typeof: ", typeof(value)  + check(typeof(value), expected));

    trace("\n" + describeType(value))
}

function check(type:String, expectedType:String):String
{
    return "\n  » " + (type == expectedType ? "good" : (type.toLowerCase() == expectedType.toLowerCase() ? "almost good" : "wrong"))
}

これにより、次の結果がトレース パネルに出力されます。

数値としての 3.5

** Input value: 3.5
** Expected: Number

getQualifiedClassName:  Number
  » good
as: Number
  » good
is: Number
  » good
describeType name:Number
  » good
typeof:  number
  » almost good

<type name="Number" base="Object" isDynamic="false" isFinal="true" isStatic="false">
  <extendsClass type="Object"/>
  <constructor>
    <parameter index="1" type="*" optional="true"/>
  </constructor>
</type>

数字としての 3

** Input value: 3
** Expected: Number

getQualifiedClassName:  int
  » wrong
as: uint
  » wrong
is: uint
  » wrong
describeType name:int
  » wrong
typeof:  number
  » almost good

<type name="int" base="Object" isDynamic="false" isFinal="true" isStatic="false">
  <extendsClass type="Object"/>
  <constructor>
    <parameter index="1" type="*" optional="true"/>
  </constructor>
</type>

-3 as Number

** Input value: -3
** Expected: Number

getQualifiedClassName:  int
  » wrong
as: int
  » wrong
is: int
  » wrong
describeType name:int
  » wrong
typeof:  number
  » almost good

<type name="int" base="Object" isDynamic="false" isFinal="true" isStatic="false">
  <extendsClass type="Object"/>
  <constructor>
    <parameter index="1" type="*" optional="true"/>
  </constructor>
</type>

単位として 3

** Input value: 3
** Expected: uint

getQualifiedClassName:  int
  » wrong
as: uint
  » good
is: uint
  » good
describeType name:int
  » wrong
typeof:  number
  » wrong

<type name="int" base="Object" isDynamic="false" isFinal="true" isStatic="false">
  <extendsClass type="Object"/>
  <constructor>
    <parameter index="1" type="*" optional="true"/>
  </constructor>
</type>

3 int

** Input value: 3
** Expected: int

getQualifiedClassName:  int
  » good
as: uint
  » wrong
is: uint
  » wrong
describeType name:int
  » good
typeof:  number
  » wrong

<type name="int" base="Object" isDynamic="false" isFinal="true" isStatic="false">
  <extendsClass type="Object"/>
  <constructor>
    <parameter index="1" type="*" optional="true"/>
  </constructor>
</type>

-3 int

** Input value: -3
** Expected: int

getQualifiedClassName:  int
  » good
as: int
  » good
is: int
  » good
describeType name:int
  » good
typeof:  number
  » wrong

<type name="int" base="Object" isDynamic="false" isFinal="true" isStatic="false">
  <extendsClass type="Object"/>
  <constructor>
    <parameter index="1" type="*" optional="true"/>
  </constructor>
</type>

分析することはたくさんありますが、いくつかのことが浮かび上がってきています。

  • Number が 3.5 の場合は Number として出力されますが、3 の場合は int/uint として出力されます。
  • それが uint か int かを検出するのは難しく、結果は混乱し、一貫性がありません。

デバッグ目的で (そしてこれがどのように機能するかを理解するために)、宣言した型が必要です。正しい型を返す関数を作成するにはどうすればよいですか?

4

3 に答える 3

5

それぞれのテストで結果が得られる理由を説明します。

なので

var value:Number = 3;
trace(value as int); // 3

as演算子は弱いキャスト演算子です。左辺の値を右辺の型にキャストし、結果として評価します。キャストできない場合は と評価されnullます。この場合、Numberは に正常にキャストされ、その後intの結果が3評価されます。

var value:Number = 3.5;
trace(value as int); // null

この例では、 の値を3.5にキャストできないintため、ステートメントは に評価されnullます。

var value:Number = 3.5;
trace(value is int); // false

is演算子は演算子に基づいていますが、キャスト オブジェクトではなく値にas評価されます。Boolean上記のコードは、

trace((value as int) != null)

あなたの目的のために、ほぼ同じことisを達成してください。asどちらも左側の値を右側の値にキャストします。キャストの型は、値の型と同じようにステートメントに関連しています。

タイプ

var value:Number = 3;
trace(typeof value); // number

typeof演算子は JavaScript (ActionScript 3 はその拡張機能) からの継承であり、JavaScript プリミティブ の表現に評価さStringます。したがって、ActionScript 3 クラス名に評価されることはないため、ActionScript 3 型システムでの使用は制限されています。例えば、typeof

var mc:MovieClip = new MovieClip();
trace(typeof mc); // object

var value:int = 3;
trace(typeof value); // number

MovieClipは確かにObjectであり、これを念頭に置いて、 が とtypeof value評価される理由が明らかになりnumberます。ActionScript 3 は、JavaScript プリミティブ をNumber独自の型intおよびuintで拡張し、コンパイラが適用および最適化します。intこれが、またはuintNumber;であるかどうかを確認するときに混乱する結果が得られる理由です。技術的には、それらは. ActionScript 3 のプリミティブは、厳密に型指定された言語という意味では、まったくプリミティブではありません。

記述タイプ

これらは、言語機能ではなく Adob​​e 機能であるため、私が最も確信を持っていない結果です。これを見てください:

var value:Number = 3;
trace(describeType(value)); // int
value += 0.1;
trace(describeType(value)); // Number

整数の場合、Flash Player は に最適化されているようvalueです。intこれはおそらく、オブジェクトのインデックスとして使用されるときにaNumberを として扱うなど、パフォーマンスの最適化を行うことができるようにするためです。これも興味深いです:intArray

var value:int = 3;
trace(describeType(value)); // int
value += 0.1;               // value is still 3
trace(describeType(value)); // int

この場合、 として明示的に定義valueしたintため、コンパイラは実行時のキャストを回避し、浮動小数点演算を無視します。

結論

ActionScript 3 プリミティブのコンパイル時のクラスを見つける良い方法は 1 つではないと思います。これらの各演算子は、何ができるかを教えてくれますが、何をしたかは教えてくれません。言語は壊れていません。それは動的ですが、時には一見するとそうです。ここでの大きな教訓は、AS3 の型システムが自分の考えを常に信頼できるとは限らないということです。uint考えられる解決策はありますが、またはintを使用すると、ypu はすべての Adob​​e 最適化を失いArrayますVector。独自の型付きオブジェクトを作成し、その上でgetQualifiedClassNameorを使用できますdescribeType

class UnsignedInteger
{
    private var v:uint = 0;

    public function UnsignedInteger(value:uint) { v = value }
    public function get value():uint { return v }
    public function set value(value:uint):void { v = value; }
 }

 var value:UnsignedInteger = new UnsignedInteger(3);
 trace(getQualifiedClassName(value)); // UnsignedInteger
于 2012-10-22T16:41:09.350 に答える
0

私の知る限り、現時点ではコンパイラを取得する方法はなく、プレーヤーはこれを最適化し、暗黙的に変換を行います。

于 2012-10-18T11:47:24.537 に答える
0

(誰かが不思議に思うなら、私は自分で解決策を見つけました。@ antonpakerの回答も必ず読んでください。有用な情報があります)

数字の正しいタイプを見つけるための信頼できる解決策があるようです。ただし、いくつかの制限があります。public vars でのみ可能で、親オブジェクトを渡す必要があります。親オブジェクトを使用するdescribeTypeと、実行時に最適化される方法ではなく、クラス プロパティの正確なタイプが得られます。オブジェクトの適切なタイプを見つけるには、オブジェクト内のプロパティを見つける必要があります。

function getNameOfTypeOfProperty(object:*, property:String):String
{
    return describeType(object)..*.(hasOwnProperty('@name') && @name == property).@type;
}

シンプルなムービークリップでこれを試してみると:

trace("x:" + getNameOfTypeOfProperty(this, "x"));
// Number

trace("currentFrame:" + getNameOfTypeOfProperty(this, "currentFrame"));
// int

これらの値は (常に) 正しいようです。

(注:この関数は、Temple ライブラリの内部バージョンの新しい Reflection モジュールに追加され、おそらく次のリリースで使用できるようになります。このクラスは、describeType 呼び出しを最適化するために、describeType も適切にキャッシュします)

于 2012-10-23T10:16:05.133 に答える