Ruby的赋值和拷贝

1 赋值
2 拷贝
3 clone和dup的区别
4 拷贝中的回调函数
5 rails中的拷贝

1 赋值
赋值是指向同一个引用,两个是同一个对象。

a = "demo"
b = a
p a.object_id #=>70198266701020
p b.object_id #=>70198266701020

#因为a,b指向同一个对象,改变其中任何一个对象,另外一个对象都会被改变。

b[0] = "x"
b #=>"xemo"
#改变b, a也会改变
a #=>"xemo"
p a.object_id #=>70198266701020
p b.object_id #=>70198266701020
两个对象相同的对象,指向同一内存地址

如果对b重新进行赋值,那么a,b为不同的对象。

a = "demo"
b = a
p a.object_id #=>70198266701020
p b.object_id #=>70198266701020

b = "xx"
a #=> "demo"
#a,b为没有关系的两个对象
p a.object_id #=>70198266701020
p b.object_id #=>70198263178200
重新赋值之后变为两个不同的对象

2 拷贝
拷贝也分为浅拷贝和深拷贝,浅拷贝涉及到两个方法分别是dup和clone。浅拷贝只拷贝对象的第一层,而对于对象的第二层以及更多的嵌套层不做拷贝,这里的拷贝是指指向新的内存空间,对于普通对象而言,只拷贝对象的第一层指向,而对于对象的属性不拷贝,对于数组和hash而言,只拷贝第一层的值,而不对第二层以及更深层次的值。深拷贝是对对象以及对象中的任何嵌套以及依赖对拷贝。
上述语言的专业描述:
拷贝的目的是为了得到两个看起来一样但是本质上又不同的对象,这里的本质体现在他们是否指向了同一个存储空间。
在Ruby中,对象的定义是一组实例变量外加一个指向其类的引用。如果其某个实例变量又依赖于另外的对象,那么这个时候我们如何来对待这个依赖的对象呢?
根据我们处理方式的不同将会得到两种不同的拷贝概念
浅拷贝:对所有的依赖对象不做拷贝,仅仅是引用
深拷贝:对所有的依赖(依赖的依赖)对象都做拷贝

针对普通字符串对象:

#普通的字符串对象,只拷贝第一层
a = "demo"
b = a.clone

#a,b是两个不同的对象
p a.object_id #=>70109624896300
p b.object_id #=>70109629296760

#普通的字符串对象,只有一层,其实做到了全部拷贝,改变a对象的值,不影响对象b的值
a[0] = "x"
a #=>"xemo"
p a.object_id #=>70109624896300
b #=>"demo"
p b.object_id #=>70109629296760

针对带有属性的对象

#对对象拷贝了第一层,对对象的第二层就是对象的属性没有进行拷贝
class Demo
  attr_accessor :name
end

obj = Demo.new
obj.name = "jayzen"
obj1 = obj.clone
p obj #=>#<Demo:0x007f87292291d0 @name="jayzen">
p obj1 #=>#<Demo:0x007f87292127c8 @name="jayzen">

#没有对对象的属性进行拷贝,属性指向同一个内存地址,改变其中一个也会改变另外一个
obj.name.sub!("j", "x")
p obj #=>#<Demo:0x007f87292291d0 @name="xayzen">
p obj1 #=>#<Demo:0x007f87292127c8 @name="xayzen">
在第一层不互相影响,第二层的属性值指向同一内存地址,会同时发生改变

针对嵌套的数组对象和嵌套的hash对象

#同样,只对第一层的数组进行拷贝,不对第二层的数组进行数组进行拷贝,同理hash

a = ["x", ["y", "z"]]
b = a.clone
#因为只拷贝第一层,所以a第一层数组变化不影响b
a[0] = "t"
a #=>["t", ["y", "z"]]
b #=>["t", ["y", "z"]]

#第二层数组没有进行拷贝,a第二层数组变化会影响b
a[1][0] = "t"
a #=>["x", ["t", "z"]]
b #=>["x", ["t", "z"]]

#hash的例子也是类似

用Marshal实现深拷贝,即是对于对象的任何一层数组都进行了拷贝

a=["x", ["y", "z"]]
b=Marshal.load(Marshal.dump(a))

a[1][0]="t"
a #=>["x", ["t", "z"]]
#因为进行了深拷贝,a的二层数组值改变之后b并没有改变
b #=>["x", ["y", "z"]]

3 clone和dup的区别
记住这两个的区别只要记住哪个比较特殊就好(和记住proc和lambda的区别类似),其中dup不会复制对象扩展的任何模块,dup不会记住被复制对象的freeze状态。

#dup不会复制扩展对象的任何模块
module Demo
  def test
    puts "this is the demo"
  end
end

class Test
end

obj = Test.new
obj.extend Demo

obj1 = obj.clone
obj1.test #=>"this is the demo"

obj2 = obj.dup
ob2.test #=>"error"

#dup不会记住被复制对象的freeze状态
str="demo"
str.freeze

str.clone.frozen? #=>true
str.dup.frozen? #=>false

4 拷贝中的回调函数
拷贝中存在三个回调函数,分别是
initialize_copy
initialize_clone
initialize_dup
上面两个方法ruby2.4中core中没有,在扩展库中的set类有,但是可以直接使用,不用require。
如果同时存在initialize_copy,initialize_clone两个方法,clone方法执行initialize_clone方法,如果要执行initialize_copy方法,需要在initialize_clone方法中执行super方法。
如果同时存在initialize_copy,initialize_dup两个方法,dup方法执行initialize_dup方法,如果要执行initialize_copy方法,需要在initialize_dup方法中执行super方法。
如果只有initialize_copy,没有其他两个方法,则执行该方法。

class Demo
  def initialize_copy(other)
    #__callee__返回的所在方法体的方法名
    puts __callee__
  end
end

Demo.new.dup #initialize_copy
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容

  • 一、 让自己熟悉Ruby 1、理解 Ruby 中的 True 在 Ruby 中,除了 false 和 nil, 其...
    Sgemini阅读 682评论 0 1
  • 本文介绍 Ruby 基本的数据类型,主要参考《Ruby编程语言》。Ruby支持的数据类型包括基本的Number、S...
    零小白阅读 12,146评论 0 11
  • 重点掌握 3 类对象和方法 对象就是一个物体 类的独特存在就是一个实例,对实例进行操作叫做方法。方法可以应用于类或...
    Coder大雄阅读 1,258评论 0 2
  • 对象的创建与销毁 Item 1: 使用static工厂方法,而不是构造函数创建对象:仅仅是创建对象的方法,并非Fa...
    孙小磊阅读 1,982评论 0 3
  • 最近快播案又出现在了公众的视野,引发了全民的关注。第一次知道快播还是在大学的时候,从一个室友的电脑里看到的,...
    冷冷123456阅读 1,807评论 0 0