设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 4753|回复: 15
打印 上一主题 下一主题

[已经解决] 求 深层 clone

 关闭 [复制链接]

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
609
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

跳转到指定楼层
1
发表于 2009-8-18 11:42:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
clone
dup
生成某对象的拷贝并返回它.

clone生成的是完整的拷贝,它包括freeze、taint和特殊方法等信息; 而dup则只拷贝对象的内容.

请注意,clone 和 dup 生成的都是"浅层(shallow)"拷贝.它们只拷贝对象本身,而不会拷贝对象的所指(例如数组的元素等).

另外,如果对拷贝进行如下测试的话

obj.equal?(obj.clone)

通常都不成立.但是

obj == obj.clone

通常都会成立.

若想对true, false, nil, Symbol对象等进行拷贝时,会引发TypeError异常.

ruby 1.7 特性: 在1.7版本中,若想对Numeric对象等immutable(内容不可改变)的对象进行拷贝时,会引发TypeError.

于是求深层clone
Marshal.dump和save_data似乎能实现深层dump,这是怎么做到的
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
2
发表于 2009-8-18 13:29:22 | 只看该作者
刚才去翻 TERENCE 关于对象克隆的提问贴,发现回档消失了……

于是送上备份的传送门:
http://szsu.spaces.live.com/blog/cns!D57D0E50BE1820CF!170.entry
回复 支持 反对

使用道具 举报

Lv1.梦旅人

CHAOS

梦石
0
星屑
107
在线时间
245 小时
注册时间
2005-11-4
帖子
3521

贵宾

3
发表于 2009-8-18 14:31:18 | 只看该作者
于是求深层clone

先Marshal.dump了,再读出来吧...
偷懒了...别打我啊= =
梦想世界,在你伸手!
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
609
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

4
 楼主| 发表于 2009-8-18 14:35:43 | 只看该作者
有些对象是不能dump的
Marshal.dump(obj[,port][,limit])
把obj递归地写入文件. 若对那些不能被写入文件的对象使用该函数时, 会引发TypeError异常. 下列对象就不能被写入文件.

无名的Class/Module对象. (此时,将引发ArgumentError异常. 请参考Module.new来了解无名类的情况.)
其状态受到系统保护的那些对象. 具体说来就是以下实例. 例如Dir, File::Stat, IO及其子类File, Socket等.
MatchData, Data, Method, UnboundMethod,Proc, Thread, ThreadGroup, Continuation的实例.
定义了特殊方法的对象
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv1.梦旅人

CHAOS

梦石
0
星屑
107
在线时间
245 小时
注册时间
2005-11-4
帖子
3521

贵宾

5
发表于 2009-8-18 14:37:32 | 只看该作者
应该可以用重写方法的办法吧= =
ruby里应该有反射吧,有这个重写起来就方便多了.
菜鸟路过.:$
梦想世界,在你伸手!
回复 支持 反对

使用道具 举报

Lv1.梦旅人

CHAOS

梦石
0
星屑
107
在线时间
245 小时
注册时间
2005-11-4
帖子
3521

贵宾

6
发表于 2009-8-18 14:40:26 | 只看该作者
还有一个办法,写一个方法,利用反射,来取得object的结构,然后递归复制.....
梦想世界,在你伸手!
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
609
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

7
 楼主| 发表于 2009-8-18 14:41:29 | 只看该作者
不是,只要去覆盖 Object 父类的 clone 方法,让浅层次克隆返回的对象的成员变量依次被克隆即可,而如果这个被克隆的成员内部还有成员,那么也应该再次被克隆(层层嵌套),这样就是深层次的克隆了,比如 Array 的深层次克隆:
  1. class Array
  2.   def clone
  3.     obj = super
  4.     for i in 0...obj.size
  5.       begin
  6.         obj[i] = self[i].clone
  7.       rescue TypeError
  8.         next
  9.       end
  10.     end
  11.     return obj
  12.   end
  13. end
复制代码
a = [[[1], 2], [3, 4]]
b = a.clone
b[0][0][0] = 32767
p a[0][0][0] # <-- 1

让一个引用变量 obj 来保存最终克隆后的对象,先调用 super 获取 Object 类提供的浅层次克隆后的本对象(是一个数组),然后枚举它的每一个元素,克隆这个元素并保存到原地,如果这个元素是一个数组,那么调用这个元素的 clone 方法就会再次重复同样的步骤,否则的话则按照原来的方式去克隆其它类型的对象~

以上引自紫苏大人给出的讨论页

这个的意思也就是说,如果要实现深层clone.那么就必须针对每个类都进行修改吗
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
8
发表于 2009-8-18 15:43:21 | 只看该作者
本帖最后由 紫苏 于 2009-8-18 15:57 编辑

Array 等 Ruby 的底层类比较特殊,因为是 C 写的,所以无法去获取这个类中的成员变量,像 Array 就只能通过 [] 方法来克隆它的元素,所以需要单独去写它的深层 clone 方法;RGSS 中的那些 Object 的徒子徒孙的话,去重写一下 Object 的 clone 就行了;至于 Sprite 啊,Tone 之类的,其内部已经覆盖了父类的 clone,就不用管了
  1. =begin

  2. class Object
  3.   alias _original_clone_ clone
  4.   def clone
  5.     obj = _original_clone_
  6.     for i in obj.instance_variables
  7.       begin
  8.         obj.instance_eval("i = i.clone")
  9.       rescue TypeError
  10.         next
  11.       end
  12.     end
  13.     return obj
  14.   end
  15. end

  16. =begin
  17. =end

  18. class A
  19.   attr_accessor :a
  20.   def initialize
  21.     @a = [1, 2, 3]
  22.   end
  23. end

  24. a = A.new
  25. b = a.clone
  26. b.a[0] = 99999
  27. p b.a, a.a
复制代码
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
609
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

9
 楼主| 发表于 2009-8-18 15:48:51 | 只看该作者
Array 等 Ruby 的底层类比较特殊,因为是 C 写的,所以无法去获取这个类中的成员变量,像 Array 就只能通过 [] 方法来克隆它的元素,所以需要单独去写它的深层 clone 方法
像这样的必须重写的类有哪些?
Hash,Module,Class,Struct?Thread?
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv3.寻梦者

孤独守望

梦石
0
星屑
3132
在线时间
1535 小时
注册时间
2006-10-16
帖子
4321

开拓者贵宾

10
发表于 2009-8-18 15:50:11 | 只看该作者
本帖最后由 IamI 于 2009-8-18 15:51 编辑

轻声告诉紫苏……懒人zh想要深层clone的是顶级自调main或者是class类的实例
(顶级自调只有在VX中有……)

顺便,把内建类下来还不够吗?to zh
菩提本非树,明镜本非台。回头自望路漫漫。不求姻缘,但求再见。
本来无一物,何处惹尘埃。风打浪吹雨不来。荒庭遍野,扶摇难接。
不知道多久更新一次的博客
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-22 04:30

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表