最近在看ruby,看到了一个关于引用的问题。先看下面一段代码:
上面定义了一个叫Song的类,方法name会返回name的值。然后:
运行代码会输出:
Bicyclops
###############
Dicyclops
tmp1和tmp2的值都是来自于song.name的返回值。然而修改tmp1后打印song.name并没有改变,而修改tmp2后打印song.name的值改变了,为什么哪?
我的理解是 tmp1 = "Tom" 这句话是先新建了一个值为“Tom”的字符串对象,然后将其引用赋给tmp1,因此tmp1与song对象的name已经是不同的引用,无论tmp1的值如何改变,song的name属性都不会变。
而tmp2[0]=“D”的操作不同,tmp2仍然与name是同一个引用,因此修改操作tmp2会引起name的同步变化。
以前无论在java还是c++编程中,为了保证数据的安全往往将数据设为私有并单独写访问器来访问数据。但是在ruby中字符串是可以更改的,像上面设定访问器仍可以在外部改变成员变量的值。因此有必要做一些改变:
将name方法按照上面这么写,会在返回name的时候做一次拷贝,返回和name不同的引用,这样就不会引起上面的问题了。
#song.rb
class Song
def initialize(name,artist,duration)
@name = name
@artist = artist
@duration = duration
end
def name
@name
end
end
上面定义了一个叫Song的类,方法name会返回name的值。然后:
#file.rb
if __FILE__ == $0
require 'song.rb'
song = Song.new("Bicyclops","Fleck",260)
tmp1 = song.name
tmp1 = "Tom"
print song.name + "\n"
print "###############\n"
tmp2 = song.name
tmp2[0] = "D"
print song.name
end
运行代码会输出:
Bicyclops
###############
Dicyclops
tmp1和tmp2的值都是来自于song.name的返回值。然而修改tmp1后打印song.name并没有改变,而修改tmp2后打印song.name的值改变了,为什么哪?
我的理解是 tmp1 = "Tom" 这句话是先新建了一个值为“Tom”的字符串对象,然后将其引用赋给tmp1,因此tmp1与song对象的name已经是不同的引用,无论tmp1的值如何改变,song的name属性都不会变。
而tmp2[0]=“D”的操作不同,tmp2仍然与name是同一个引用,因此修改操作tmp2会引起name的同步变化。
以前无论在java还是c++编程中,为了保证数据的安全往往将数据设为私有并单独写访问器来访问数据。但是在ruby中字符串是可以更改的,像上面设定访问器仍可以在外部改变成员变量的值。因此有必要做一些改变:
def name
@name.dup
end
将name方法按照上面这么写,会在返回name的时候做一次拷贝,返回和name不同的引用,这样就不会引起上面的问题了。