关于在ruby hash中赋值的奇怪之处

时间:2011-12-16 01:44:04

标签: ruby

以下两种情况看起来相似,但结果不同。有趣的是,也许有人会犯这样的错误。

CASE1

class A
    def initialize
        @a = @b = @c = @d = @e = {}
        @e["e"] = "eeeeee"

        puts @a
        puts @b
        puts @c
        puts @d
        puts @e
    end
end
a = A.new

给出:

{"e"=>"eeeeee"}
{"e"=>"eeeeee"}
{"e"=>"eeeeee"}
{"e"=>"eeeeee"}
{"e"=>"eeeeee"}

案例2

class B
    def initialize
        @a = @b = @c = @d = @e = {}
        @e = {"e" => "eeeeee"}

        puts @a
        puts @b
        puts @c
        puts @d
        puts @e
    end
end
b = B.new

给出:

{}
{}
{}
{}
{"e"=>"eeeeee"}

修改

结果在CASE 1和CASE 3之间不同,但是它们以相同的方式分配值。

案例3

class C
    def initialize
        @a = {}
        @b = {}
        @c = {}
        @d = {}
        @e = {}
        @e["e"] = "eeeee"

        puts @a
        puts @b
        puts @c
        puts @d
        puts @e
    end
end

c = C.new

#the result of case 3
{}
{}
{}
{}
{"e"=>"eeeee"}

2 个答案:

答案 0 :(得分:1)

它没有做“同样的事情”。 @e["e"] = "eeeeee"在几个变量指向的现有哈希中设置键["e"]@e = {"e" => "eeeeee"}为变量@e分配一个新哈希,它不会更改其他变量。

答案 1 :(得分:1)

不同的行为是因为ruby没有完成任务的完整副本。

您可以在控制台中进行探索。尝试

a = {"foo" => "bar"}
b = a                  # b and a are references to the same hash object
a["foo"] = "baz"       # changes the underlying hash
b                    

你得到=> {"foo"=>"baz"},因为你所做的是创建一个哈希对象并将a绑定到该对象,然后将b绑定到与a相同的对象(即,它们都是对同一对象的引用)。因此,当您更改a时,您正在更改基础对象,当您检查b时,您会看到相同的更改!这与您在案例1(b = a = {"foo" => "bar"}

中执行此操作时的情况相同

在您的CASE 2中,您通过将所有5个变量绑定到同一个哈希对象,以相同的方式开始。但是,您将@e分配给新哈希。就好像你这样做了

b = a = {"foo" => "bar"}
b = {"foo" => "baz"}      # replacing b with a reference to a new hash object

在你的CASE 3中,你将所有5个变量绑定到独立的哈希对象,所以当你改变一个它独立于其他哈希对象时,一个la

a = {"foo" => "bar"}  
b = {"foo" => "bar"}  # b and a reference independent hash objects
b["foo"] = "baz"

例如,请参阅http://ruby.about.com/od/advancedruby/a/deepcopy.htm