如何在应用程序中的所有类之间共享数组? [英] How to share an Array between all Classes in an application?

查看:194
本文介绍了如何在应用程序中的所有类之间共享数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想共享一个Array,所有类都可以在该数组中获取和更改数据。像全局数组或多点访问数组。 ActionScript 3.0如何实现这一点?

解决方案

由于这个问题最近被连接了,我还会添加一些东西。我曾经被提议在单独使用之前使用它,并且一旦意识到命名空间和引用是如何工作的,并且基于全局变量的所有东西都是不好的想法,就会放弃使用。



备选



注意这仅仅是一个展示,我不建议您在整个地方使用这种方法。 >



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

  public class Global {
public static const myArray:Alternative = new Alternative();
}

并几乎像单身人士一样使用它:

  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,10);
trace(ga [5]); // 5

您的 Alternative.as 看起来类似于singleton one :

 包adnss.projects.tchqs 
{

import flash.utils.Proxy ;
import flash.utils.flash_proxy;

public class Alternative扩展代理
{
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函数getProperty(id:*):* {var i:int = id;
return _data [i + =(i <0)? _data.length:0];
// return _data [id]; //没有肛门项目访问的版本 - var i:int可以被删除。
}

覆盖flash_proxy函数setProperty(id:*,value:*):void {var i:int = id;
if(_dispatching){throw new Error(你不能在DATA_CHANGE事件处理时设置数据);返回; }
i + =(i <0)? _data.length:0;
if(i> 9){throw new Error(你可以不用推送就只覆盖前10个项目);返回;}
_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;
/ **
*在替换现有索引处的数据后分派。
* @eventType adnss.projects.tchqs.GDataEvent
* /
[Event(name =dataChange,type =adnss.projects.tchqs.GDataEvent)]
/ **
*在将新数据推入两个数组之后分派。
* @eventType adnss.projects.tchqs.GDataEvent
* /
[Event(name =newData,type =adnss.projects.tchqs.GDataEvent)]
class AltEventDisp extends EventDispatcher {}

Singleton的唯一不同之处在于,您实际上可以有多个这样的实例所以你可以像这样重用它:

  public class Global {
public static const myArray:Alternative = new Alternative ();
public static const myArray2:Alternative = new Alternative();

$ / code>

具有两个分离的全局数组,甚至可以将它作为实例变量时间。

注意

使用像 myArray.get(x) myArray [x] 显然比访问原始数组慢(请参阅我们正在采取的所有其他步骤在 setProperty )。

  public static const staticArray:Array = [1 1,2,3]; 

另一方面,您对此没有任何控制权。数组的内容可以在任何地方更改。

关于事件的警告



我必须补充一点,如果您想要以这种方式访问​​数据你应该小心。与每个锋利的刀片一样,它很容易被切割。
例如,考虑当你这样做时会发生什么:

  private function onDataChange(e:GDataEvent):void { 
trace(dataChanged at:,e.id,to,Global.myArray [e.id]);
Global.myArray [e.id] ++;
trace(在函数退出前调用new onDataChange);

该函数在数组中的数据被更改后调用,数据再次。基本上它类似于做这样的事情:
$ b $ pre $ 函数f(x:Number){
f(++ x) ;





$ b

如果您切换 myArray.blockCircularChange 。有时候你会故意想要这样的递归,但很可能你会这样做不小心。不幸的是,闪光灯会突然停止这种事件发送,甚至没有告诉你为什么,这可能会令人困惑。

下载完整示例 here

为什么在大多数情况下使用全局变量是不好的?



我想有很多关于整个互联网的信息,但要完成,我会添加一个简单的例子。



考虑你在你的应用程序中有一些视图,你显示一些文本,或图形,或最有可能的游戏内容。假设你有象棋游戏。 Mayby你已经在两个类中分离了逻辑和图形,但是你希望两个都在同一个棋子上运行。所以你创建你的 Global.pawns 变量并在 Grahpics Logic class。



一切都很随和,完美无瑕。现在你有了一个好主意 - 为用户添加选项,一次播放两场比赛甚至更多。所有你需要做的就是创建你的匹配的另一个实例......对吗?

那么你注定在这一点上,因为你的类的每个实例将使用同样的 Global.pawns 数组。你不仅有全局变量,而且你也限制了自己只能使用每个使用这个变量的类的单个实例:/ b

因此,在你使用任何全局变量之前,只要想想,如果你想存储的东西在你的整个应用程序中真的是全球性和通用性的话。

I want to share an Array which all classes can "get" and "change" data inside that array. Something like a Global array or Multi Access array. How this is possible with ActionScript 3.0 ?

解决方案

As this question was linked recently I would add something also. I was proposed to use singleton ages ago and resigned on using it as soon as I realized how namespaces and references work and that having everything based on global variables is bad idea.

Aternative

Note this is just a showcase and I do not advice you to use such approach all over the place.

As for alternative to singleton you could have:

public class Global {
    public static const myArray:Alternative = new Alternative();
}

and use it almost like 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

And your Alternative.as would look similar to singleton one:

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 { }

The only difference form Singleton is that you can actually have multiple instances of this class so you can reuse it like this:

public class Global {
    public static const myArray:Alternative = new Alternative();
    public static const myArray2:Alternative = new Alternative();
}

to have two separated global arrays or even us it as instance variable at the same time.

Note

Wrapping array like this an using methods like myArray.get(x) or myArray[x] is obviously slower than accessing raw array (see all additional steps we are taking at setProperty).

public static const staticArray:Array = [1,2,3];

On the other hand you don't have any control over this. And the content of the array can be changed form anywhere.

Caution about events

I would have to add that if you want to involve events in accessing data that way you should be careful. As with every sharp blade it's easy to get cut. For example consider what happens when you do this this:

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"); 
}

The function is called after data in array was changed and inside that function you changing the data again. Basically it's similar to doing something like this:

function f(x:Number) {
    f(++x);
}

You can see what happens in such case if you toggle myArray.blockCircularChange. Sometimes you would intentionally want to have such recursion but it is likely that you will do it "by accident". Unfortunately flash will suddenly stop such events dispatching without even telling you why and this could be confusing.

Download full example here

Why using global variables is bad in most scenarios?

I guess there is many info about that all over the internet but to be complete I will add simple example.

Consider you have in your app some view where you display some text, or graphics, or most likely game content. Say you have chess game. Mayby you have separated logic and graphics in two classes but you want both to operate on the same pawns. So you create your Global.pawns variable and use that in both Grahpics and Logic class.

Everything is randy-dandy and works flawlessly. Now You come with the great idea - add option for user to play two matches at once or even more. All you have to do is to create another instance of your match... right?

Well you are doomed at this point because, every single instance of your class will use the same Global.pawns array. You not only have this variable global but also you have limited yourself to use only single instance of each class that use this variable :/

So before you use any global variables, just think twice if the thing you want to store in it is really global and universal across your entire app.

这篇关于如何在应用程序中的所有类之间共享数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆