【问题标题】:Detecting the difference between uint, int and Number in ActionScript 3在 ActionScript 3 中检测 uint、int 和 Number 之间的区别
【发布时间】:2012-10-08 17:28:58
【问题描述】:

我想获得我的号码的声明类型,但我不知道如何获得它们。于是我写了一个可能检测方法的测试:

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,结果令人困惑且不一致。

出于调试目的(并且只是为了了解其工作原理),我想要我声明的类型。如何创建一个返回正确类型的函数?

【问题讨论】:

  • 看看这个:var a:Number = 3; trace(getQualifiedClassName(a));//int a+=.5; trace(getQualifiedClassName(a));//编号

标签: actionscript-3 flash actionscript types numbers


【解决方案1】:

我会解释为什么你的每个测试都会给你它们的结果。

作为

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)

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

类型

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

typeof 运算符是 JavaScript(ActionScript 3 是其扩展)的保留,计算结果为 JavaScriptprimitiveString 表示。因此,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 的计算结果为number 的原因就很明显了。 ActionScript 3 使用自己的类型 intuint 扩展了 Number 的 JavaScript 原语,编译器随后会强制执行和优化它们。这就是为什么在检查 intuint 是否为 Number 时会得到令人困惑的结果;从技术上讲,他们是。 ActionScript 3 原语根本不是真正的原语,至少在强类型语言的意义上不是。

描述类型

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

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

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

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

在这种情况下,因为我们将value 显式定义为int,所以编译器会避免运行时强制转换并忽略浮点运算。

结论

我认为没有单一的好方法可以找到 ActionScript 3 原语的编译时类。这些运算符中的每一个都会告诉你你可以做什么,但不会告诉你你做了什么。语言不坏;它是动态的,但有时具有欺骗性。最大的教训是你不应该总是相信 AS3 中的类型系统会按照你的想法去做。我能想到一个解决方案,但是当在ArrayVector 上使用uintint 时,ypu 将失去所有的Adobe 优化。您可以创建自己的类型化对象,并在其上使用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

【讨论】:

  • 哇,感谢您的精彩评论!我非常感谢您在这篇文章中投入的时间,这非常有帮助。我还做了一些额外的研究并找到了一种获取确切类型的方法,但这仅适用于公共变量,您还必须传递父对象。我会在这个线程中发布代码。
【解决方案2】:

据我所知,目前还没有办法让编译器得到它,播放器会优化它并为你隐式转换。

【讨论】:

    【解决方案3】:

    (如果有人想知道,我自己找到了解决方案。请务必阅读 @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 library内部版本的新反射模块中,并且可能会在下一个版本中可用。这个类也很好地缓存了describeType,用于优化describeType调用)

    【讨论】:

    • 有趣!很高兴你找到了一些有用的东西。多么棘手的问题。
    猜你喜欢
    • 2011-08-06
    • 2016-03-23
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-31
    • 1970-01-01
    相关资源
    最近更新 更多