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 作为数字

** 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 作为整数

** 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 作为整数

** 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无法将 的值强制转换为 an,int因此该语句的计算结果为null

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

is运算符建立在运算符的基础上as,但计算为一个Boolean值而不是一个强制转换对象。上面的代码是一样的,

trace((value as int) != null)

因此,出于您的目的,isas完成大致相同的事情。它们都将左侧值转换为右侧值。转换类型与语句的相关性与值的类型一样。

类型

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

typeof运算符是 JavaScript(ActionScript 3 是其扩展)的保留,并计算为StringJavaScript原语的表示。因此,typeof它在 ActionScript 3 类型系统中的用途有限,因为它永远不会评估为 ActionScript 3 类名。例如,

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

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

MovieClip确实是Object,考虑到这一点,为什么typeof value评估为就很明显了numberNumberActionScript 3使用自己的类型int和扩展了 JavaScript 原语,uint编译器随后会强制执行和优化。这就是为什么在检查一个intoruint是否是一个Number;时你会得到令人困惑的结果。从技术上讲,它们是。ActionScript 3 原语根本不是真正的原语,至少在强类型语言的意义上不是。

描述类型

这些是我最不确定的结果,因为它不是语言功能,而是 Adob​​e 功能。看看这个:

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

value当它是一个int整数时,Flash Player 似乎正在优化。这可能是为了让他们可以进行性能优化,例如在将 aNumber用作对象int的索引时将其视为 an Array。同样有趣的是:

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

在这种情况下,因为我们明确定义valueint,编译器避免了运行时强制转换并忽略了浮点运算。

结论

我认为没有单一的好方法可以找到 ActionScript 3 原语的编译时类。这些操作员中的每一个都会告诉您您可以做什么,但不会告诉您您做了什么。语言不坏;它是动态的,但有时具有欺骗性。最大的教训是你不应该总是相信 AS3 中的类型系统会按照你的想法去做。有一个我能想到的解决方案,但是当使用uintor inton Arrayor时,ypu 会丢失所有 Adob​​e 优化Vector。您可以创建自己的类型化对象,并在其上使用getQualifiedClassNamedescribeType

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 的答案,它有有用的信息)

似乎有一个可靠的解决方案可以找到正确的号码类型。但是有一些限制;只有公共变量才有可能,并且您必须传递父对象。如果您使用describeType父对象给出了类属性的确切类型,而不是它在运行时的优化方式。您必须找到对象内部的属性才能找到它的正确类型。

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

如果你在一个简单的 MovieClip 上试试这个:

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

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

这些价值观似乎(总是)正确。

(注意:这个函数将被添加到Temple 库内部版本的新反射模块中,并且可能会在下一个版本中可用。这个类也很好地缓存了 describeType,用于优化 describeType 调用

于 2012-10-23T10:16:05.133 回答