Project1

标题: 残脑帖,来说说rmxp储存后的阿尔西斯还是原来的阿尔西斯吗 [打印本页]

作者: enghao_lim    时间: 2010-11-17 14:57
标题: 残脑帖,来说说rmxp储存后的阿尔西斯还是原来的阿尔西斯吗
本帖最后由 越前リョーマ 于 2013-8-22 21:36 编辑

如题,具体请看:
  1. class A
  2.   def initialize(n)
  3.     @value = n
  4.   end
  5. end
  6. a = [] # 假设A为$game_actors
  7. b = [] # 假设B为$game_party.actors
  8. (0..9).each{|i|a.push(A.new(i))}
  9. b.push(a[0])
  10. p a[0] == b[0] # true
  11. # 记录过后再读档
  12. a = Marshal.load(Marshal.dump(a))
  13. b = Marshal.load(Marshal.dump(b))
  14. p a[0] == b[0] # false
复制代码
就如以上原来的a[0]已经不是b[0]了……
所以大家来说说储存后原本的阿尔西斯是不是原来的阿尔西斯呢?

真实答案:

作者: 匿名    时间: 2010-11-17 15:04
黑幕曰:“你永远无法确定前一秒或后一秒的你还是你”
作者: EngShun    时间: 2010-11-17 15:14
本帖最后由 EngShun 于 2010-11-17 15:14 编辑

这么深奥的问题还是找其他人吧。
作者: dukesward    时间: 2010-11-17 15:14
发完这贴LZ就不是LZ了
作者: minimini    时间: 2010-11-17 15:21
提示: 作者被禁止或删除 内容自动屏蔽
作者: 精灵使者    时间: 2010-11-17 16:39
本帖最后由 精灵使者 于 2010-11-17 16:40 编辑

b = Marshal.load(Marshal.dump(b))
MS这句话读取的不是存档的A内容,是么?
作者: fux2    时间: 2010-11-17 16:51
那个A.new.........
作者: ~屎猴子~    时间: 2010-11-17 16:53
、、、、
表示我不在意、、
XP无爱、、
阿尔西斯无爱、、
作者: 风雪优游    时间: 2010-11-17 17:02
Anonymous 发表于 2010-11-17 15:04
黑幕曰:“你永远无法确定前一秒或后一秒的你还是你”

认同此物,并发现一个BUG
作者: 874609281    时间: 2010-11-17 17:31
都叫阿尔西斯,都是阿尔西斯...
作者: 阿夏依岚    时间: 2010-11-17 17:43
不明真相的群众表示回帖查看=。=
脚本盲
作者: 一瞬间的幻觉    时间: 2010-11-17 17:50
你每天睡醒了,也不是你了,因为脑细胞已经代谢更新换了一大批
作者: 埋風葬月    时间: 2010-11-17 18:37
提示: 作者被禁止或删除 内容自动屏蔽
作者: 禾西    时间: 2010-11-17 18:40
你投胎了還是你嗎?嗯……這是個問題。
作者: zh99998    时间: 2010-11-17 19:00
虽然你写的答案是true,但是似乎不太对吧,你那个根本就没Marshal过。。内部的$game_party.actors[0] 和 $game_actors[1]指向的是同一个对象,要是把其中一个Marshal一下再读出来,就不是同一个了

至于关心【是不是同一个】到底有什么意义,请看
a = [1, 2]
b = a
b.push 3
p a #=> [1,2,3]
尽管从表面上看起来只对b做了修改,但是a却也发生了变化,这是因为b和a是【同一个】数组

作者: SVM伟    时间: 2010-11-17 19:26
Anonymous 发表于 2010-11-17 15:04
黑幕曰:“你永远无法确定前一秒或后一秒的你还是你”

不知道为什么我这么想引用
作者: a554187203    时间: 2010-11-17 19:29
当然是,作为神的阿尔西斯有无数的身外化身
作者: 做游戏的新手    时间: 2010-11-17 19:38
应该是吧……
作者: enghao_lim    时间: 2010-11-17 19:46
本帖最后由 enghao_lim 于 2010-11-17 19:51 编辑

回复 zh99998 的帖子

我说的是储存之前与储存之后始终都是true,所以是一样的。
原因是因为Game_Party只对@actors进行读取作用,所以最后的操作还是返回Game_Actor,
相反的人物仓库直接对@actors进行读写,所以操作不需要返回Game_Actor导致人物出现克隆状态。

a = [1,2]
b = a
b.push(3)
这样在克隆前的确不会有任何变化,可是Marshal.load(Marshal.dump(b))之后,两者将不再关联,虽然他们之前是同一个东西的说。

简单来说因为存档有着更深clone的意义,所以才会提出这个……==
就好像
  1. class A
  2. end
  3. a = A.new
  4. b = a.clone
  5. p a == b
复制代码
返回false是一样的。
作者: 月色半人家    时间: 2010-11-17 20:40
当我发完这个帖子的时候。我其实已经变了
作者: 苏小脉    时间: 2010-11-17 21:18
Game_Actor 可以覆盖父类的 Object#== 方法,进行属性相等关系的判定,而不是进行对象在内存中的身份测试。:)
作者: 雪翼飞马    时间: 2010-11-17 22:42
好吧我是白痴,一点也不明白………………
作者: 精灵使者    时间: 2010-11-18 07:53
这个应该是与数组的污染有关(b数组污染了a数组)
刚才葬花君指定的那个东西……
建议将@actors 返回到正常的GAME_ACTOR下再进行保存(?)
作者: 沙之爱罗    时间: 2010-11-18 08:57
其实我是LZ的马甲,所以我其实是楼主
作者: 懒De说    时间: 2010-11-18 12:57
这个问题需要好好思考一下
作者: 纸飞机哟    时间: 2010-11-18 12:58
风雪爆内幕了!

作者: Lillian.K    时间: 2010-11-18 13:13
菜鸟飘过……完全没有概念……
作者: 雪孩子    时间: 2010-11-22 21:50
提示: 作者被禁止或删除 内容自动屏蔽
作者: 雪孩子    时间: 2010-11-22 21:51
提示: 作者被禁止或删除 内容自动屏蔽
作者: FireFox    时间: 2010-11-22 22:10
打个比方(不知道郑不正确):阿尔西斯进入人物仓库,储存,再读取,RMXP辨认人物仓库内的阿尔西斯与数据库的阿尔西斯不相同,尽管他们的属性,名称,等级等等。。。都一模一样
作者: 光的圆周率    时间: 2010-11-22 22:45
根据政治学矛盾的统一性,此时的阿尔西斯已经不是过去的阿尔西斯了
作者: xuwl0928    时间: 2010-11-22 22:55
提示: 作者被禁止或删除 内容自动屏蔽
作者: 七千    时间: 2010-11-22 22:56
这到底什么东西啊- -
作者: 逍游    时间: 2010-11-22 23:01
看看答案是什么
作者: cinderelmini    时间: 2010-11-22 23:05
某脑残的木子相信,阿尔就只有一个。。。。。。
虽然目前还不知道那段脚本是怎么运行的。。。
(看不懂啦。。。)
作者: 涛涛    时间: 2010-11-22 23:54
提示: 作者被禁止或删除 内容自动屏蔽
作者: px.凤翔九天    时间: 2010-11-23 00:09
本帖最后由 px.凤翔九天 于 2010-11-23 00:11 编辑

恩恩,为看答案的回复,我觉得不是....
哦,原来我错了....恩恩,继续修炼脚本去.....
貌似用事件配合脚本做人物仓库更安全....
作者: miracl    时间: 2010-11-23 08:15
= =忽然想起那句经典的台词:你大爷还是你大爷……
作者: EngShun    时间: 2010-11-23 11:28
回复 miracl 的帖子

你大爷跌倒后已经不是原本的你大爷了,因为他多了个伤口。
作者: 459645195    时间: 2010-11-23 11:32
我认为阿尔卑斯只有一个
作者: 不是马甲    时间: 2010-12-5 17:49
此时的你不是彼时的你··············(好邪恶的诡辩论)
作者: 764454923    时间: 2010-12-5 20:33
到底是什么
作者: 白鬼    时间: 2010-12-6 18:04
我觉得这个问题涉及到了哲学领域
作者: Expert    时间: 2010-12-6 19:50
提示: 作者被禁止或删除 内容自动屏蔽
作者: Expert    时间: 2010-12-6 19:50
提示: 作者被禁止或删除 内容自动屏蔽
作者: 苏小脉    时间: 2010-12-7 04:37
enghao_lim  感觉好像有些明白又有些不明白XD

默认是判断对象的身份(identity)是否相同,把这个概念移植到 C 层面就是判断对象结构体的内存地址的相等性。Ruby 的Object#== 方法底层是这样:

  1. VALUE
  2. rb_obj_equal(VALUE obj1, VALUE obj2)
  3. {
  4.     if (obj1 == obj2) return Qtrue;
  5.     return Qfalse;
  6. }
复制代码

  1. rb_define_method(rb_cBasicObject, "==", rb_obj_equal, 1);
复制代码
C 的 `==' 运算符用在指针上时就是比较地址了。

在 Ruby 中,可以做如下的覆盖:

  1. class Student
  2.         attr :id
  3.         attr :name
  4.         def initialize(id, name)
  5.                 @id = id
  6.                 @name = name
  7.         end
  8.         def ==(student)
  9.                 return @id == student.id && @name == student.name
  10.         end
  11. end

  12. student = Student.new(100001, "阿尔西斯")
  13. p student == Marshal.load(Marshal.dump(student)) # true
复制代码
就可以看见输出是 true 了:handshake
作者: 魔之哆啦    时间: 2010-12-9 19:38
...........阿尔西斯吗...


魔之哆啦于2010-12-9 19:38补充以下内容:
...........阿尔西斯吗...
作者: 黑崎一护    时间: 2010-12-23 16:31
让我想起了苏格拉底与柏拉图...
作者: chaochao    时间: 2010-12-23 19:30
人物仓库什么的,存ID就行了,没必要连对象一起存进去。
反序列化什么的其实是新建了一个对象,这个新建的对象已经不是原来的对象了。
其实$game_party.actors里存的是通过ID从$game_actors里找到的人物,所以两个才是一样的。而前面那个是两次反序列化得到的两个不同的对象。


chaochao于2010-12-23 20:12补充以下内容:
如果是我的人物仓库的话,你看看Scene_Load里的 read_save_data方法的最后有没有$game_party.refresh这句,如果没有,你是不是改过代码或者用其它人的代码导致了这个问题。嘛,没有就加上吧。
作者: 冷星云    时间: 2010-12-23 21:18
回帖后LZ还是LZ马-0-? 好吧 我提前选了第一项
作者: yangff    时间: 2010-12-23 21:46
Not define =


yangff于2010-12-23 21:46补充以下内容:
Not define =
作者: 连贴大侠    时间: 2010-12-24 07:01
替换队员有一个东西叫做初始化,所以阿尔西斯还是阿尔西斯.
作者: tamashii    时间: 2010-12-24 08:23
不是了吧,大概……
作者: 苏小脉    时间: 2010-12-24 23:43
chaochao  另外这种做法用不好就会异常,为什么?自己想去。楼主说的这种情况,其实完全没必要这么做。  发表于 9 小时前

chaochao  实际的项目中,几十个属性什么的复杂的结构是很常见的,你如果是因为楼主说的原因而要这么搞,那我就要佩服你的耐心或者你对机器速度的信心

请不要做这个假设,我没有针对 RM 这种在初始化时就把所有数据库数据保存到内存中的持久对象的情况($game_* 引用的对象)。因为默认 RM 的数据库数据都是静态的,且内存中已经有一份拷贝,那自然可以只操作标识了。“实际的项目中”是不可能一次性把数据库数据都装载到内存中的,所以为了从表中获取对象及其属性,就需要让集合的元素成为对象这个类型。比如 Hibernate 的 criteria,默认就是返回一个 Collection<Object>,元素实际的类型是关系数据库映射到 Java 的对象类型。
作者: 老夫子    时间: 2010-12-24 23:58
……高深莫测……
作者: chaochao    时间: 2010-12-25 04:20
本帖最后由 chaochao 于 2010-12-25 04:34 编辑

回复 苏小脉 的帖子

嘛,嘛……数据库里的ID,你是不能修改的。所以才用ID来表示一个对象。而且所有的副本也都是从数据库这个唯一的地方取出的,修改也是要向数据库发送数据的。总之对数据库中数据的操作,也都是在对数据库这一个地方操作,Hibernate其实就相当于减少了程序员与数据库交互的代码,使数据库的操作看起来更像面向对象的程序。
大多数情况下,客户端的数据经过了客户端的修改,如果没有更新到数据库,通常都是无效的,数据依然以数据库读取的为准。这样的情况正好是我说的RM中必须要注意的情况。总之副本的修改是无效的。但与数据库情况不同的是RM的副本与正本是在同一个域的,所以非常容易混淆。那么我才不建议这么搞。我的意思是,不需要副本的时候,千万不要用副本。

PS:反正我只在讨论RM,要讨论其它东西,还是算了。
作者: 苏小脉    时间: 2010-12-25 10:19
回复 chaochao 的帖子
而且所有的副本也都是从数据库这个唯一的地方取出的,修改也是要向数据库发送数据的。总之对数据库中数据的操作,也都是在对数据库这一个地方操作,Hibernate其实就相当于减少了程序员与数据库交互的代码,使数据库的操作看起来更像面向对象的程序。

实际的应用中充斥着动态数据,有时可能会希望把动态数据维持到数据库中,而对于使用  Hibernate 的人来说,规范就是建立一个 transient 的对象,之后用 Transaction#commit 使其持久。但在此之前,如果你想做个域的重复值检测(即如果表中已经有一行包含了特定的几个域的相同值就不 commit),传统的做法自然是操纵列的 UNIQUE CONSTRAINT,但如果出于某种原因你不想 ALTER 列的属性,就只能让 Hibernate 把数据 SELECT 出来,然后挨个比较映射后的对象全部属性了。默认的 Object#== 自然做不到这一点,所以让子类覆盖。

我很赞同你上面关于避免数据库对象副本的观点,普通的 RM 游戏确实完全不需要这么干。然而覆盖 Object#== 只是一个思路,可以用来定义某个类型元素的相等性二元关系。只有有了二元关系,各种集合论中的问题才能解决,比如求并集。这个思路并不是针对和 RM 数据库数据挂钩的对象类型,完全可以应用在更宏观的场合,而在该场合下会可能会无法避免地出现对象的拷贝。以前有人提过一个在用 RM 时遇见的这样的问题,就是找一个方位向量集合中所有重合的方位向量,重合的向量对象在内存中身份不同,但 (x, y) 相同。

另外,如果你说的“佩服你的耐心”是出于属性太多的原因,那在支持反射成员变量的语言中压根儿不是问题。
作者: a19981007a    时间: 2010-12-25 12:36
真相飘过····
作者: 越前リョーマ    时间: 2010-12-25 15:06
阿尔西斯永远只有一个——只不过他会分身术!
作者: chaochao    时间: 2010-12-25 16:41
回复 苏小脉 的帖子

在数据库的操作中,Transaction是保证数据正确的手段,而普通的程序是不需要这么做的。Hibernate把数据查询出来挨个比较,挨个比较什么的的完全没有必要吧,不是有HQL嘛……Hibernate实际上也在尽可能避免一些瓶颈。
至于一些特殊情况必须要用副本的,我也是支持用副本的。
作者: ksheng121    时间: 2010-12-25 16:42
提示: 作者被禁止或删除 内容自动屏蔽
作者: 黑白旋律    时间: 2010-12-25 17:11
如此深奥,脚本盲路过
作者: bzzdhm    时间: 2010-12-25 18:11
不是说回复才能浏览么
作者: 逸豫    时间: 2010-12-26 12:18
  1. class A
  2.   def initialize(n)
  3.     @value = n
  4.   end
  5.   def ==(obj)
  6.     return self.eql?(obj)
  7.   end
  8.   def hash
  9.     return @value.hash
  10.   end
  11.   def eql?(obj)
  12.     return self.hash == obj.hash
  13.   end
  14. end
  15. a = []
  16. b = []
  17. a.push(A.new("Fuckit"))
  18. b[0] = a[0]
  19. p a[0] == b[0]
  20. a = Marshal.load(Marshal.dump(a))
  21. b = Marshal.load(Marshal.dump(b))
  22. p a[0].==(b[0]) #=>True
  23. #Marshal后实例的object_id改变了
复制代码

作者: CrystalineSnow    时间: 2010-12-26 15:38
提示: 作者被禁止或删除 内容自动屏蔽
作者: 新手小白    时间: 2010-12-26 15:39
果断选择了3
作者: rpg549007821    时间: 2011-4-4 04:38
真实答案是?否
作者: 快乐·小赵    时间: 2011-4-4 07:35
提示: 作者被禁止或删除 内容自动屏蔽
作者: lianran123456    时间: 2011-4-4 09:39
................
坑定还是
淡定淡定
作者: MeowSnow    时间: 2011-4-4 18:40
看不懂脚本哦······{:nm_3:}
作者: 独孤剑圣    时间: 2011-4-4 19:13
应该不是
作者: 失落迷白    时间: 2011-4-4 23:20
阿尔西斯都百年修行了,身子虽在异处但心还是跟着你滴 -~~~~~
作者: galaxys    时间: 2011-4-5 09:13
果然超蛋疼的……阿尔西斯永远活在我们心中……
作者: starky_ds    时间: 2011-4-5 13:39
杯具的PASCAL飘过...
作者: 被遗弃的    时间: 2011-4-5 13:50
真是答案是?
作者: 琦琦    时间: 2012-5-5 07:42
我是来看答案的
作者: 小学生    时间: 2012-5-5 08:22
false。。
作者: 漫画朱古力    时间: 2012-5-5 08:33
反正看着还是阿尔西斯就行了...
作者: hys111111    时间: 2012-5-5 13:00
还是吧,都没有改变actor什么的
作者: ☆恒皇杨之神★    时间: 2012-5-5 13:10
看了这帖后我才发现我不认识阿尔西斯了..
作者: 荷包PIG蛋    时间: 2012-5-5 16:55
果断选择3,我是VA档+脚本盲哇哇!!
作者: maju_saka    时间: 2012-6-22 14:51
详情请参见高中政治课本……这是个让你学了以后什么也不再相信的神物……
作者: 不灭的火炎    时间: 2012-8-28 22:29
阿尔西斯永远只有一个!!
作者: 天使喝可乐    时间: 2012-8-29 10:43
所以我果断删除了阿尔西斯
作者: 鄢炎餍    时间: 2012-8-29 10:46
什么= =原来是坟
作者: 咕噜    时间: 2012-8-29 10:51
= =不明真像我吓了我还以为一夜之间二级热门贴出现了
作者: 这货就是不填坑    时间: 2012-8-29 11:02
好深奥哦
作者: 普京    时间: 2012-8-29 12:36
卧槽这么早的坟都挖出来了!
作者: 黑色的笔    时间: 2012-8-29 13:00
看不懂= =
作者: 没是的人    时间: 2012-8-29 13:34
=.=水区居然还可以设置回复可见。。。




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1