Ole*_*nko 5 flex3 actionscript-3
我需要在每个其他对象中都有一个共同对象的实例.我正在对每个子对象中的对象值进行修改.
例如.我有一张瓷砖地图,一个机器人按特定顺序移动它们.每个机器人都标记着已经被他访问过的瓷砖,因为访问=真.但总的来说我不希望改变主地图......
我试图建立一个例子:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
applicationComplete="complete()">
<mx:Script>
<![CDATA[
private var array:Array = new Array( 1, 2, 3, 4);
public function complete():void
{
trace("here " + array);
var a:Array = array;
a[0] = 100;
trace("here " + array);
}
]]>
</mx:Script>
</mx:Application>
Run Code Online (Sandbox Code Playgroud)
有人可以帮我理解如何通过值(不是通过引用)复制数组,例如数组
Ali*_*aru 10
对于克隆数组,您可以使用Array.slice.
var arrCopy:Array = arrOrig.slice();
Run Code Online (Sandbox Code Playgroud)
function clone ( arr:Array ):Array
{
return arr.map( function( item:*, ..r ):*
{
return item;
} );
}
Run Code Online (Sandbox Code Playgroud)
可能包含一些语法错误......
public class MyObject
{
private var arr:Array;
private var bool:Boolean;
// ...
public function clone ():MyObject
{
var obj:MyObject = new MyObject();
// clone values
obj.arr = this.arr.slice();
obj.bool = this.bool;
return obj;
}
}
Run Code Online (Sandbox Code Playgroud)
这是poke描述的方法的替代方法:
我首先想对poke的帖子提出一些观点.
"为该特定对象定义自己的克隆函数.没有任何特殊函数可以自动为任意对象执行此操作." 假.ActionScript有一个内置的序列化方法,称为AMF(ActionScript消息格式).AMF可用于执行非基本对象的副本.
"使用自定义克隆方法有很大的优势,你可以准确地决定将要复制什么,以及如何复制它......"这正是你序列化一个对象时所做的,所以没有什么大的优点您的自定义克隆方法比序列化方法.
"......并且返回类型是正确的(即你不需要施放)." 您也不需要强制转换序列化对象.但序列化具有通用的附加好处,使得复制动态的功能,而不仅限于特定类型.
"[实现一个接口](鉴于clone返回一个特殊类型的对象,这将是非常不合适的)"必须定义一个返回类型会使进程静态,从而锁定您使用特定类型.如果我们使用该语言的动态属性,我们可以创建一个通用克隆方法而不关心类型.对此没什么不妥.
"如果你对序列化对象进行两次反序列化,你会得到一个对象的副本,这只是序列化的另一个影响." 通过调用slice()或concat()而不使用任何参数获得数组副本的事实只是这些方法的副作用.我真的没有在这里看到你的观点.此外,序列化的核心是复制.序列化然后反序列化的行为是制作副本的行为.你不会以某种方式获得完全相同的内存,引用和所有完整.
我有一个问题:你如何在克隆方法中处理嵌套的非原始类型?
在你的问题中,你说"有人可以帮我理解我如何复制例如数组,按值,而不是通过引用"我认为,在复制对象时,了解浅拷贝和深拷贝之间的区别很重要.
浅拷贝
这里提供的解决方案(Array.slice()和Array.concat())称为浅拷贝.你得到的是数组的副本.如果数组的内容是基本类型(通过值而不是通过引用传递的那些),那么您有两个唯一对象,原始对象和副本.但是,如果您的数组包含通过引用传递的对象,则数组的原始数据和副本将具有完全相同的内容.如果对原始数组中的对象进行更改,则更改将反映在复制的数组中.虽然这有时可能是你想要的,但并非总是如此.
深拷贝
深层副本将遍历您要复制的对象的层次结构,并复制它找到的任何对象.然后,您将被允许对复制的对象进行任何更改,而不会在原始对象中反映任何更改.
如果要按照poke建议定义自定义克隆方法,则复制非原始类型会变得过于复杂.您必须遍历对象的属性并在任何非基本类型上调用自定义clone()方法.但是,如果遇到像Array或Dictionary这样的内置非基本类型,那么你必须重新创建对象,遍历其内容,并通过检查它是否是非原始的来重新开始,调用它的clone()方法,如果它有一个,或处理数组和字典.它变得过于复杂.总而言之,这个方法有两个问题:你必须自己处理Arrays和Dictionaries(以及任何内置的非原始类型); 您必须在嵌套对象上专门调用clone方法(并且知道它们已定义了clone方法).
另一种方法是使用AMF序列化然后反序列化对象,为您提供深层复制.这对于Arrays,Dictionaries以及依赖于公共属性的任何非原语都是开箱即用的.
var t:Array = [];
t[0] = [1, 2, 3];
t[1] = new Dictionary();
t[1]['hello'] = 'world';
t[2] = {'my': 'object'}
trace(t, t[1]['hello'], t[2]['my']); // [trace] 1,2,3,[object Dictionary],[object Object] world object
var t2:Array = clone(t);
trace(t2, t2[1]['hello'], t2[2]['my']); // [trace] 1,2,3,[object Dictionary],[object Object] world object
t[0] = [4, 5, 6];
t[1]['hello'] = 'earth';
t[2]['my'] = 'other object';
trace('modified values'); // [trace] modified values
trace(t, t[1]['hello'], t[2]['my']); // [trace] 4,5,6,[object Dictionary],[object Object] earth other object
trace(t2, t2[1]['hello'], t2[2]['my']); // [trace] 1,2,3,[object Dictionary],[object Object] world object
function clone(source:*):* {
var b:ByteArray = new ByteArray();
b.writeObject(source);
b.position = 0;
return(b.readObject());
}
Run Code Online (Sandbox Code Playgroud)
这涵盖了自定义克隆方法的第一个问题,以及上面的第一个问题.如您所见,所有对象及其内容都是使用内置方法复制的.
我在这里展示了如何创建克隆方法的实现,但您可以在:mx.utils.ObjectUtil中找到一个.
如果要深度复制一个私有存储其数据的对象,则必须实现IExternalizable接口.这将迫使您实现两种方法:
public function writeExternal(output:IDataOutput):void
public function readExternal(input:IDataInput):void
Run Code Online (Sandbox Code Playgroud)
在这些函数中,您将私有变量写入输出对象,然后从输入到私有变量读取它们.然后,当您调用clone时,您将获得对象的完整副本.请记住对所有嵌套对象执行此操作.
这是一个包含两个类的简单实现示例:
package {
import flash.utils.IExternalizable;
import flash.utils.IDataInput;
import flash.utils.IDataOutput;
import flash.net.registerClassAlias;
public class Car implements IExternalizable {
private var type:String;
private var contents:Array;
public function Car() {
registerClassAlias("Car", Car);
}
public function setVars(type:String, contents:Array):void {
this.type = type;
this.contents = contents;
}
public function setType(type:String):void {
this.type = type;
}
public function writeExternal(output:IDataOutput):void {
output.writeUTF(type);
output.writeObject(contents);
}
public function readExternal(input:IDataInput):void {
type = input.readUTF();
contents = input.readObject();
}
public function toString():String {
return "[Car type = " + type + ", contents = " + contents + "]";
}
}
}
Run Code Online (Sandbox Code Playgroud)
和:
package {
import flash.utils.IExternalizable;
import flash.utils.IDataInput;
import flash.utils.IDataOutput;
import flash.net.registerClassAlias;
public class Person implements IExternalizable {
private var firstName:String;
private var secondName:String;
public function Person() {
registerClassAlias("Person", Person);
}
public function setVars(firstName:String, secondName:String):void {
this.firstName = firstName;
this.secondName = secondName;
}
public function writeExternal(output:IDataOutput):void {
output.writeUTF(firstName);
output.writeUTF(secondName);
}
public function readExternal(input:IDataInput):void {
firstName = input.readUTF();
secondName = input.readUTF();
}
public function toString():String {
return "[Person firstName = " + firstName + ", secondName = " + secondName + "]";
}
}
}
Run Code Online (Sandbox Code Playgroud)
测试它们:
package {
import flash.display.Sprite;
import flash.utils.ByteArray;
import flash.utils.Dictionary;
public class Serial extends Sprite {
public function Serial() {
var person0:Person = new Person();
person0.setVars("John", "Doe");
var person1:Person = new Person();
person1.setVars("Jane", "Doe");
var car0:Car = new Car();
car0.setVars("Ford", [person0, person1]);
var person2:Person = new Person();
person2.setVars("Joe", "Bloggs");
var car1:Car = new Car();
car1.setVars("Vauxhall", [person2]);
var street:Array = [car0, car1];
trace("street = " + street); // [trace] street = [Car type = Ford, contents = [Person firstName = John, secondName = Doe],[Person firstName = Jane, secondName = Doe]],[Car type = Vauxhall, contents = [Person firstName = Joe, secondName = Bloggs]]
var street2:Array = clone(street);
trace("street2 = " + street2); // [trace] street2 = [Car type = Ford, contents = [Person firstName = John, secondName = Doe],[Person firstName = Jane, secondName = Doe]],[Car type = Vauxhall, contents = [Person firstName = Joe, secondName = Bloggs]]
person0.setVars("Max", "Headroom");
person1.setVars("Simon", "Le Bon");
car0.setType("Mini");
person2.setVars("Harry", "Wotsit");
car1.setType("Austin");
trace("modified values of street"); // [trace] modified values of street
trace("street = " + street); // [trace] street = [Car type = Mini, contents = [Person firstName = Max, secondName = Headroom],[Person firstName = Simon, secondName = Le Bon]],[Car type = Austin, contents = [Person firstName = Harry, secondName = Wotsit]]
trace("street2 = " + street2); // [trace] street2 = [Car type = Ford, contents = [Person firstName = John, secondName = Doe],[Person firstName = Jane, secondName = Doe]],[Car type = Vauxhall, contents = [Person firstName = Joe, secondName = Bloggs]]
}
private function clone(source:*):* {
var b:ByteArray = new ByteArray();
b.writeObject(source);
b.position = 0;
return(b.readObject());
}
}
}
Run Code Online (Sandbox Code Playgroud)
这涵盖了自定义克隆方法的第二个问题.正如您所看到的,我们不必担心调用任何克隆方法,这一切都得到了我们的关注.
我并不是说它并非完全没有缺点,但它确实为深度复制对象提供了一些功能.
一些缺点包括:
请参阅Adobe关于复制阵列的观点:http://livedocs.adobe.com/flex/3/html/help.html?content = 10_Lists_of_data_6.html
另请注意,Adobe从Java中窃取了这种技术.
| 归档时间: |
|
| 查看次数: |
6083 次 |
| 最近记录: |