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

Project1

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

[讨论]RUBY中破坏性的方法有哪些?

 关闭 [复制链接]

Lv1.梦旅人

龙皇

梦石
0
星屑
50
在线时间
83 小时
注册时间
2007-8-8
帖子
2956
跳转到指定楼层
1
发表于 2009-5-29 04:56:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
●破坏性的方法(destructive methods)
此谓当还有其他变数参考到与接收者相同一个物件时,
用破坏性方法改变数时该变数也会改。

EX:(以pop阵列末端取出元素的操作为例)

p a = [1,2,3,4] #=> [1,2,3,4]
p b = a         #=> [1,2,3,4]
p b.pop         #=> 4
p b.pop         #=> 3
p b.pop         #=> 2
p b             #=> [1]
p a             #=> [1]



popshift都有这个现象。

pop方法删除元素后,变数b被改变时,同时变数a也被改变了!
这是因为执行 a=b 时,并不是将a的内容复制给b,
事实上a和b代表同一个物件

所以使用破坏性的方法都要小心!

故此我想要问RUBY中破坏性的方法除了popshift外还有哪些?
版务信息:本贴由楼主自主结贴~

                签名图来自:無限のファンタジア
                 我的RMXP专题空间--龙使传说

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
2
发表于 2009-5-29 05:43:56 | 只看该作者
这个是对象的引用,如果你直接把一个对象赋值给另一个对象,那么就是一个引用拷贝的过程,两个数组对象指向的是同一个地址,所以无论改变哪一个数组都会改变同一块内存~
可以利用对象的克隆机制让对象在内存中完全复制一份再把地址赋给引用变量,这样两个相同内容的对象就指向两块不同的独立的内存了
至于这种会改变本身的方法有很多,比如 String 的 gsub!、swapase!,Array 的 compact!、uniq! 等带感叹号的原地(in-place)算法的都会有这种现象~
版主对此帖的认可:『参与讨论的好孩子。』,积分『+300』。
回复 支持 反对

使用道具 举报

Lv1.梦旅人

天壤

梦石
0
星屑
50
在线时间
1 小时
注册时间
2008-7-18
帖子
1435
3
发表于 2009-5-29 05:46:06 | 只看该作者
弱弱的人.....

只是路过...

好久没来了~
时隔多年。我还是觉得66才是我的家。
回复 支持 反对

使用道具 举报

Lv1.梦旅人

龙皇

梦石
0
星屑
50
在线时间
83 小时
注册时间
2007-8-8
帖子
2956
4
 楼主| 发表于 2009-5-29 06:00:01 | 只看该作者
以下引用紫苏于2009-5-28 21:43:56的发言:

这个是对象的引用,如果你直接把一个对象赋值给另一个对象,那么就是一个引用拷贝的过程,两个数组对象指向的是同一个地址,所以无论改变哪一个数组都会改变同一块内存~
可以利用对象的克隆机制让对象在内存中完全复制一份再把地址赋给引用变量,这样两个相同内容的对象就指向两块不同的独立的内存了
至于这种会改变本身的方法有很多,比如 String 的 gsub!、swapase!,Array 的 compact!、uniq! 等带感叹号的原地(in-place)算法的都会有这种现象~

也就是說
破坏性的方法  通常會加上「!」作為叮嚀??

另外如何克隆对象??

                签名图来自:無限のファンタジア
                 我的RMXP专题空间--龙使传说
回复 支持 反对

使用道具 举报

Lv1.梦旅人

龙皇

梦石
0
星屑
50
在线时间
83 小时
注册时间
2007-8-8
帖子
2956
5
 楼主| 发表于 2009-5-29 06:36:56 | 只看该作者
话说帖子被点亮悬赏图标?? 谢谢先~~~

但话说我没悬赏呢!

版主对此帖的评论:『3小时内请勿……嗯,前辈早安。』,积分『-50』。这些被扣积分的一半会用于对本帖正确答案的悬赏。

                签名图来自:無限のファンタジア
                 我的RMXP专题空间--龙使传说
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2006-10-7
帖子
28
6
发表于 2009-5-29 07:41:41 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
6875
在线时间
1666 小时
注册时间
2008-10-29
帖子
6710

贵宾

7
发表于 2009-5-29 08:15:34 | 只看该作者
好吧!我算是明白clone是干嘛的了
以前看教程 柳柳说到这个clone就跳过去了没有详细解释

也明白为什么for循环的临时变量改变的属性会反映在实变量身上去
我一直就没搞懂这个问题来着,这下算是明白了{/cy}











你知道得太多了

回复 支持 反对

使用道具 举报

Lv1.梦旅人

龙皇

梦石
0
星屑
50
在线时间
83 小时
注册时间
2007-8-8
帖子
2956
8
 楼主| 发表于 2009-5-29 08:30:31 | 只看该作者
以下引用杨飞云于2009-5-28 23:41:41的发言:
不过如果要克隆自己设计的类的对象,比如一个 Window 的子类包含了另外一个 Window 对象,需要去重载 clone 来实现深层次的克隆,也就是递归调用各个实例成员对象的 clone 方法,否则的话仅仅是拷贝了这个 Window 类对象本身,而没有拷贝它的成员变量的对象~

也就是说只能做到表层复制??

a = [[1,1],[2,2],[3,3]]
b = a.clone
a[0].push 9
p a #=> [[1,1,9],[2,2],[3,3]]

# b的元素也会被影响??
p b #=> [[1,1,9],[2,2],[3,3]]


另问:
我刚刚在书上发现dup
而dup与clone近乎有相同功能

不同的是
dup只会复制内容,
而clone会连同特殊方法污染旗标(taint?)、冻结资讯(frozen?)一并复制

何谓
污染旗标(taint?)
冻结资讯(frozen?)

特殊方法又是因为什么才叫特殊方法??

                签名图来自:無限のファンタジア
                 我的RMXP专题空间--龙使传说
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
9
发表于 2009-5-29 13:23:33 | 只看该作者
dup只会复制内容,
而clone会连同特殊方法、污染旗标(taint?)、冻结资讯(frozen?)一并复制

你书上这样说的话其实有点问题 ^__^
dup 和 clone 都会拷贝对象的污染状态,但 dup 不会拷贝对象的冻结状态,这就是区别~

也就是说只能做到表层复制??

不是,只要去覆盖 Object 父类的 clone 方法,让浅层次克隆返回的对象的成员变量依次被克隆即可,而如果这个被克隆的成员内部还有成员,那么也应该再次被克隆(层层嵌套),这样就是深层次的克隆了,比如 Array 的深层次克隆:
class Array
  def clone
    obj = super
    for i in 0...obj.size
      begin
        obj = self.clone
      rescue TypeError
        next
      end
    end
    return obj
  end
end

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

上面的循环中会捕获到 TypeError 异常,因为 Fixnum 是不可克隆的,所以在枚举到 Fixnum 的时候就会跳过这个元素~不知道 Ruby 标准库中有没有提供判断对象本身是否可克隆的方法,Java 中就可以,所有可克隆的对象都实现了 Cloneable 接口……

何谓
污染旗标(taint?)

你的书中应该有讲到吧~我简单说一下 =)

对象污染的机制主要是为了保证程序运行的安全性~比如在脚本中调用了 eval 解释另一段脚本,而这段脚本却是来自外部的一段未知内容的脚本,这很明显是一个安全隐患。盲目地去执行这段脚本很可能会导致各种各样的问题,比如重要文件被篡改,密码被盗取等……{/fn}所以如果一个对象衍生于外部(即不在程序中),Ruby 会自动将其标记为“被污染的”,比如从文件、网路输入流中读取的字符串,操作系统环境变量等~

Ruby 对被污染对象的管理随着安全等级的不同而不同。所谓安全等级其实就是一个常量,保存在 $SAFE 中,当 $SAFE 是 0(默认)的时候不会检查被污染的对象,大于等于 1 的时候就会禁止污染对象在可能导致危险的操作中使用(至于更高的安全等级就查书吧,反正高于 1 就有可能会禁止使用被污染对象了),比如从文件读取了一段脚本保存到一个 String 对象中,然后传递给 eval,就会抛出一个 SecurityError 异常~

一个简单的例子:
$SAFE = 2

str = "damn"
str.taint

eval(str)  # Error!
执行到 eval 的时候抛出了一个安全异常,说调用 eval 不安全,这就是由于 str 是被污染的(当然抛出异常的过程是在 eval 内部进行的,会通过 tainted? 判断传递进来的参数是否被污染)

何谓
冻结资讯(frozen?)

这个很简单,就是冻结一个对象,让它无法被修改了~{/cy}要注意它冻结的是对象本身,而不是一个引用变量 =)
arr = [1, 2, 3, 4]
arr.freeze
arr[1] = 3 # Error!
尝试改变数组元素的值的时候发生了 TypeError 异常……

而特殊方法又是因为什么才叫特殊方法??

这个……还真不知道什么特殊方法不会被 dup 复制{/hx}
刚才试了下,跟访问权限没关系诶
版主对此帖的认可:『参与讨论的好孩子。』,积分『+300』。
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (暗夜天使)

精灵族の天使

梦石
0
星屑
1697
在线时间
3038 小时
注册时间
2007-3-16
帖子
33731

开拓者贵宾

10
发表于 2009-5-29 15:09:22 | 只看该作者
已经冻结的变量和常量(恒量)的管理方法应该是一样的吧。
怎样解除已经冻结的变量?
其实这个破坏的方法是有用处的,例如我经常要用到。
只需要修改一个修改区的变量就可以更改其他的数据区和功能区的变量,而不用繁琐的反复引用。
关于污染旗标,在RM里面最明显的就是用一些脚本来进行解密——如果能直接提升RM脚本中污染旗标的等级其实是最好的一种反解密的方法。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2025-1-12 03:47

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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