【问题标题】:ActionScript: Is there ever a good reason to use 'as' casting?ActionScript:是否有充分的理由使用“as”强制转换?
【发布时间】:2010-11-03 01:07:26
【问题描述】:

根据我对 ActionScript 的理解,有两种类型的强制转换:

var bar0:Bar = someObj as Bar;  // "as" casting
var bar1:Bar = Bar(someObj); // "class name" casting (for want of a better name)

另外,如果我在这里错了,请纠正我,as 转换将返回类的实例或 null,而“类名”转换将返回类的实例或引发如果强制转换是不可能的,则例外——除此之外,它们是相同的。

不过,鉴于此,as 强制转换似乎严重违反了 fail-fast-fail-early 原则......而且我很难想象使用@987654325 更可取的情况@ cast 而不是类名转换(可能会在其中抛出instanceof)。

那么,我的问题是:在什么情况下最好使用as 强制转换?

【问题讨论】:

  • 请注意,通常有用的后期绑定与您对 fffe 的解释直接冲突。
  • 是的,这在 ActionScript 中也是不可避免的,因为没有“泛型”的概念,所以你从容器中得到的东西将是无类型的。
  • (因此最好在var foo:Foo = Foo(myArray[i]) 上失败,而不是在其他地方处理 NPX)

标签: actionscript-3


【解决方案1】:

本次讨论有几点值得注意。

两者的工作方式有很大不同,Class() 将尝试将对象强制转换为指定的类,但如果失败,则会(有时取决于数据类型)抛出运行时错误。另一方面,使用 object 作为 Class 将首先执行类型检查,如果指定的 object 不能强制转换为指示的 Class,则返回 null 值。

这是一个非常重要的区别,在开发中是一个有用的工具。它允许我们执行以下操作:

var o:MyClass = myArray[i] as MyClass;

if(o)
{
    //do stuff
}

我认为它的用处非常明显。

“as”也更符合语言的其余部分(即:“myObject is MyClass”)。

MyClass() 方法在处理简单数据类型(int、Number、uint、string)时有额外的好处,例如:

var s:String = "89567";
var s2:String = "89 cat";
var n:Number = 1.9897;

var i:int = int(s); // i is = 89567, cast works
var i2:int = int(s2); //Can't convert so i2 is set to 0
var i3:int = int(n); // i = 1
var n2:Number = Number(s2); // fails, n2 = NaN

//when used in equations you'll get very different results
var result:int = int(n) * 10; //result is 10
var result:int = n * 10; //result is 19.89700
var result:int = int(s2) * 10; //result is 0

trace(s2 as Number); //outputs null
trace(s2 as int); //outputs null
trace(Number(s2)); //outputs NaN

这是一个很好且重要的话题,一般来说,我在使用 Objects 时使用“as”,在使用更简单的数据类型时使用 Cast(),但这正是我喜欢构建代码的方式。

【讨论】:

  • as 可能更符合语言,但不是更危险吗?不过感谢您的回复 - 很高兴知道 int/string/number 转换的复杂性。
  • 你觉得它更危险的是什么?危险的是不能正确处理所有情况,但这是开发人员问题而不是语言问题。我实际上觉得它更安全(类型检查),并且非常有用,并且可以产生更清晰的代码。 var o:Class = a[i] as Class ||新类(); //非常适合这种事情
  • 澄清为什么我认为它更安全:它允许您尝试类型转换而不会在失败时破坏事物。
  • 由于您指定的原因,这就是我通常的投射方式。我想优雅地处理空值。运行时错误可能会产生奇怪的意外影响,使用“as”可以避免这种情况,而无需使用 try/catch 块来处理这种情况。
【解决方案2】:

您需要在两种情况下使用as进行转换:转换为Date,以及转换为Array

对于日期,对Date(xxx) 的调用与新Date().toString() 的行为相同。

对于数组,调用Array(xxx) 将创建一个带有一个元素的Array:xxx。

Class() 转换方法已被​​证明比as 转换更快,因此在效率很重要时(以及不使用日期和数组时),它可能比as 更可取。

import flash.utils.*;

var d = Date( 1 );

trace( "'" + d, "'is type of: ",getQualifiedClassName( d ) );

var a:Array = Array( d );

trace( "'" + a, "' is type of: ", getQualifiedClassName( a ) );

    //OUTPUT
        //'Mon Jun 15 12:12:14 GMT-0400 2009 'is type of:  String
        //'Mon Jun 15 12:12:14 GMT-0400 2009 ' is type of:  Array

    //COMPILER ERRORS/WARNINGS:
        //Warning: 3575: Date(x) behaves the same as new Date().toString(). 
        //To cast a value to type Date use "x as Date" instead of Date(x).
        //Warning: 1112: Array(x) behaves the same as new Array(x).
        //To cast a value to type Array use the expression x as Array instead of Array(x).

`

【讨论】:

    【解决方案3】:

    他们实际上做不同的事情......当你说

    myvar as ClassName
    

    你实际上只是让编译器知道这个对象要么是 ClassName 要么是 ClassName 的子类

    当你说:

    ClassName(myvar)
    

    它实际上试图将其转换为那种类型的对象。

    因此,如果您的对象是该类的一个或一个后裔,并且您不需要转换它,您将使用 as

    例子:

    var myvar:String = '<data/>';
    var othervar:XML = XML(myvar); //right
    
    var myvar:String = '<data/>';
    var othervar:XML = (myvar as XML); //wrong
    
    var myvar:XML = <data/>;
    var othervar:XML = myvar as XML; // right
    

    【讨论】:

    • 好吧,我明白了。那么,是否有可能定义我自己的类型强制规则?例如,如果我要编写一个 Color 类,我如何告诉编译器 Color(0x443322) 是“0x44 红色、0x33 绿色和 0x22 蓝色的颜色”?
    • @David 不确定您的 Color 类是如何设置的,但它们通常设置为 uint。通常期待颜色的东西实际上是期待 uint。前面的 0x 表示 0x443322 是一个十六进制数,转换为 4469438 uint。所以你不应该改变它,但如果你这样做,我认为最好的方法是创建一个静态方法,比如 Color.toColor(0x443322);
    【解决方案4】:

    对数组使用“as”。

    var badArray:Array;
    badArray = Array(obj);
    

    将产生一个长度为 1 的数组,原始数组位于第一个元素中。如果你像下面这样使用'as',你会得到预期的结果。

    var goodArray:Array;
    goodArray = obj as Array;
    

    通常,在 ActionScript 中,'as' 比 'Class()' 更可取,因为它的行为更像是其他语言中的强制转换。

    【讨论】:

    • 当你说“其他语言”时,你想到的是哪一种?我确信如果您尝试执行错误的强制转换,Java 会引发异常......
    • 如果您执行 List list = (List)obj;,Java 将正确转换列表。没有例外,没有问题。你在 AS 中做 Array(obj),问题。
    【解决方案5】:

    当我有一个对象的 ArrayCollection 并且需要枚举它们时使用它,或者使用选择器函数。

    例如

    var abc:mytype = mycollection.getItemAt(i) as mytype

    【讨论】:

    • 但是你为什么使用as 而不是var abc:MyType = MyType(mycollection.getItemAt(i))?如果mycollection 包含不是MyType 的内容,则使用as 可能会出现细微的错误(请参阅快速失败规则)
    • 我使用它是因为对我来说 MyType(...) 在心理上是一个演员,而“as MyType”在心理上是一个别名,我不是在投射它,而是断言这就是它的目的编译器很高兴(即使在这种情况下它们可能相同)。但我正处于钟形曲线的鸭式末端,所以这可能主要反映了我对代码的看法——我宁愿让它清晰而简单,在所有角落都扣上纽扣。我很高兴他们单独留下了 javascript,而不是用它来制作动作脚本。我还经常使用另一个答案中提到的“if(!object){}”构造。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    • 2011-01-09
    • 2013-06-04
    • 2010-10-18
    • 2010-09-16
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多