Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何在应用程序中的所有类之间共享数组?_Arrays_Actionscript 3_Class_Get_Share - Fatal编程技术网

Arrays 如何在应用程序中的所有类之间共享数组?

Arrays 如何在应用程序中的所有类之间共享数组?,arrays,actionscript-3,class,get,share,Arrays,Actionscript 3,Class,Get,Share,我想共享一个数组,所有类都可以在该数组中“获取”和“更改”数据。类似于全局数组或多访问数组的内容。ActionScript 3.0如何实现这一点 注意:我不鼓励使用全局变量 但这是你的答案 您可以转到默认包,创建一个与全局变量同名的文件,并将全局变量设置为公共: //File: GlobalArray.as package { public var GlobalArray:Array = []; } 就这样!你有一个全局变量。您可以通过代码(从任何地方)进行如下访问: functio

我想共享一个数组,所有类都可以在该数组中“获取”和“更改”数据。类似于全局数组或多访问数组的内容。ActionScript 3.0如何实现这一点

注意:我不鼓励使用全局变量

但这是你的答案

您可以转到默认包,创建一个与全局变量同名的文件,并将全局变量设置为公共:

//File: GlobalArray.as

package {
    public var GlobalArray:Array = [];
}
就这样!你有一个全局变量。您可以通过代码(从任何地方)进行如下访问:

function DoSomething() {
    GlobalArray.push(new Object());
    GlobalArray.pop();
    for each (var object:* in GlobalArray) {
        //...
    }
}
public class Global {
    public static const myArray:Alternative = new Alternative();
    public static const myArray2:Alternative = new Alternative();
}
function f(x:Number) {
    f(++x);
}

有几种方法可以解决这个问题。一种是使用全局变量(正如unkiwii的回答中所建议的),但这在ActionScript中不是一种非常常见的方法。更常见的方法是:

类变量(静态变量) 创建名为
DataModel
或类似的类,并将该类上的数组变量定义为static:

public class DataModel {
    public static var myArray : Array = [];
}
然后,您可以使用
DataModel.myArray
从应用程序中的任何部分访问它。这很少是一个好的解决方案,因为(像全局变量一样),应用程序的一部分无法知道应用程序的另一部分何时修改了数组的内容。这意味着,即使您的数据输入GUI向数组中添加了一个对象,您的数据列表GUI也不知道如何显示新数据,除非您实现了其他方法来告诉它重新绘制

单件包装数组 另一种方法是创建一个名为ArraySingleton的类,该类包装实际数组并提供对其的访问方法,并且可以使用非常常见的将单个实例保存在静态变量中的singleton模式来访问其实例

public class ArraySingleton {
    private var _array : Array;

    private static var _instance : ArraySingleton;


    public static function get INSTANCE() : ArraySingleton {
        if (!_instance)
            _instance = new ArraySingleton();

        return _instance;
    }


    public function ArraySingleton() {
        _array = [];
    }


    public function get length() : uint {
        return _array.length;
    }

    public function push(object : *) : void {
        _array.push(object);
    }

    public function itemAt(idx : uint) : * {
        return _array[idx];
    }
}
此类包装一个数组,可以通过
ArraySingleton.instance
访问单个实例。这意味着您可以执行以下操作:

var arr : ArraySingleton = ArraySingleton.INSTANCE;
arr.push('a');
arr.push('b');
trace(arr.length); // traces '2'
trace(arr.itemAt(0)); // trace 'a'
这样做的最大好处是,您可以在添加项或以任何其他方式修改数组时发送事件,以便应用程序的所有部分都可以收到此类更改的通知。您可能希望通过实现更多类似数组的接口来扩展上面的示例,如pop()、shift()、unshift()等

依赖注入 大规模应用程序开发中的一种常见模式称为依赖项注入,这基本上意味着,通过以某种方式标记类(通常使用AS3元数据),您可以发出信号,表明框架应该“注入”该类的引用。这样,类就不需要关心引用来自何处,但框架将确保它在那里


AS3的一个非常流行的DI框架是。

由于最近链接了这个问题,我还想添加一些内容。很久以前就有人建议我使用单例,当我意识到名称空间和引用是如何工作的,并且所有东西都基于全局变量是个坏主意时,我就放弃了使用它

土生土长的 注意这只是一个展示,我不建议你在所有地方都使用这种方法

至于单身的替代方案,您可以:

public class Global {
    public static const myArray:Alternative = new Alternative();
}
并像使用singleton一样使用它:

var ga:Alternative = Global.myArray;
ga.e.addEventListener(GDataEvent.NEW_DATA, onNewData);
ga.e.addEventListener(GDataEvent.DATA_CHANGE, onDataChange);
ga.push(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "ten");
trace(ga[5]); // 5
以及您的备选方案。因为看起来类似于单例:

package adnss.projects.tchqs 
{
    
    import flash.utils.Proxy;
    import flash.utils.flash_proxy;

    public class Alternative extends Proxy
    {
        private var _data:Array = [];
        private var _events:AltEventDisp = new AltEventDisp();
        private var _dispatching:Boolean = false;
        public var blockCircularChange:Boolean = true;
        
        public function Alternative() {}
        
        override flash_proxy function getProperty(id:*):* {var i:int = id;
            return _data[i += (i < 0) ? _data.length : 0];
            //return _data[id]; //version without anal item access - var i:int could be removed. 
        }
        
        override flash_proxy function setProperty(id:*, value:*):void { var i:int = id;
            if (_dispatching) { throw new Error("You cannot set data while DATA_CHANGE event is dipatching"); return; }
            i += (i < 0) ? _data.length : 0;
            if (i > 9 ) { throw new Error ("You can override only first 10 items without using push."); return;}
            _data[i] = value;
            if (blockCircularChange) _dispatching = true;
            _events.dispatchEvent(new GDataEvent(GDataEvent.DATA_CHANGE, i));
            _dispatching = false;
        }
        
        public function push(...rest) {
            var c:uint = -_data.length + _data.push.apply(null, rest);
            _events.dispatchEvent(new GDataEvent(GDataEvent.NEW_DATA, _data.length - c, c));
        }
        
        public function get length():uint { return _data.length; }
        
        public function get e():AltEventDisp { return _events; }
        
        public function toString():String { return String(_data); }
    }

}

import flash.events.EventDispatcher;
/**
 * Dispatched after data at existing index is replaced. 
 * @eventType   adnss.projects.tchqs.GDataEvent
 */
[Event(name = "dataChange", type = "adnss.projects.tchqs.GDataEvent")]
/**
 * Dispatched after new data is pushed intwo array.
 * @eventType   adnss.projects.tchqs.GDataEvent
 */
[Event(name = "newData", type = "adnss.projects.tchqs.GDataEvent")]
class AltEventDisp extends EventDispatcher { }
使用两个分离的全局数组,甚至可以同时将其作为实例变量使用

注意

使用
myArray.get(x)
myArray[x]
等方法包装这样的数组显然比访问原始数组慢(请参阅我们在
setProperty
中采取的所有其他步骤)

另一方面,你无法控制这一切。数组的内容可以在任何地方更改

对事件的警告 我必须补充一点,如果你想让事件以这种方式访问数据,你应该小心。就像每一把锋利的刀片一样,它很容易被割伤。 例如,考虑当你这样做时会发生什么:

private function onDataChange(e:GDataEvent):void {
    trace("dataChanged at:", e.id, "to", Global.myArray[e.id]);
    Global.myArray[e.id]++;
    trace("new onDataChange is called before function exits"); 
}
该函数在数组中的数据更改后调用,在该函数中,您可以再次更改数据。基本上类似于这样做:

function DoSomething() {
    GlobalArray.push(new Object());
    GlobalArray.pop();
    for each (var object:* in GlobalArray) {
        //...
    }
}
public class Global {
    public static const myArray:Alternative = new Alternative();
    public static const myArray2:Alternative = new Alternative();
}
function f(x:Number) {
    f(++x);
}
如果切换
myArray.blockCircularChange
,您可以看到在这种情况下会发生什么。有时,您可能会有意地想要进行这样的递归,但很可能是“偶然”进行的。不幸的是,flash会突然停止此类事件,甚至不告诉您原因,这可能会令人困惑

下载完整示例

为什么在大多数情况下使用全局变量是不好的? 我想在互联网上有很多关于这方面的信息,但为了完整起见,我将添加一个简单的例子

假设您的应用程序中有一些视图,其中显示一些文本、图形或最可能的游戏内容。说你有象棋比赛。也许你已经在两个类中分离了逻辑和图形,但是你想在同一个棋子上操作它们。因此,您创建了
Global.pawns
变量,并在
Grahpics
Logic
类中使用它

一切都是完美的,完美无瑕。现在您有了一个很棒的主意-添加选项,用户可以同时玩两场比赛,甚至更多。你所要做的就是创建另一个匹配实例。。。对吧?

在这一点上,您注定要失败,因为您的类的每个实例都将使用相同的
Global.pawns
数组。您不仅拥有此全局变量,而且还限制自己仅使用使用此变量的每个类的单个实例:/


因此,在使用任何全局变量之前,请仔细考虑您要存储在其中的东西是否在整个应用程序中都是全局的和通用的。

我已经测试过了,它适合我。我不知道你编码了什么。但是这个例子非常好用。它可以在单个类中工作,但是你能用一个全局/公共数组放置一个包含3个独立类的ezample吗?
getProperty(id::*
接受任何参数