在一行上实例化两个实例时发生意外的 Ruby 行为
Unexpected Ruby behavior when instantiating two instances on one line
我创建了一个 class 为每个实例生成不同的名称,但是在一个语句中实例化两个实例时测试意外失败。
这里是 class.
class Robot
attr_accessor :name
@@current_name = 'AA000'
def initialize
@name = @@current_name
@@current_name.next!
end
end
此处 class 的行为符合预期
irb(main):009:0> Robot.new.name
=> "AA001"
irb(main):010:0> Robot.new.name
=> "AA002"
这是意想不到的行为,我期待 false
。此代码正在对我试图通过的练习进行测试,因此我无法更改测试。
irb(main):011:0> Robot.new.name == Robot.new.name
=> true
检查 object_id
显示正在创建两个不同的实例。
irb(main):012:0> Robot.new.object_id == Robot.new.object_id
=> false
为什么 Ruby 这样做,我应该如何修复它 & 假设有一个术语,我可以在搜索中输入什么来找到关于这个问题的答案。
看看这是否有帮助:
class Robot
attr_accessor :name
@@current_name = 'AA000'
def initialize
@name = @@current_name
@@current_name.next!
end
end
x = Robot.new
puts x.name
y = Robot.new
puts y.name
puts x.name == y.name
puts x.name
puts y.name
--output:--
AA001
AA002
true
AA002
AA002
Why is Ruby doing this
因为每个实例的 @name
变量引用与变量 @@current_name
相同的字符串,并且您不断使用 !
方法更改该字符串。
what should I do to fix it
class Robot
attr_accessor :name
@@current_name = 'AA000'
def initialize
@name = @@current_name.dup
@@current_name.next!
end
end
x = Robot.new
puts x.name
y = Robot.new
puts y.name
p x.name == y.name
p x.name
p y.name
--output:--
AA000
AA001
false
AA000
AA001
尽管如此,我和许多其他人会警告您永远不要在代码中使用 @@variables
。
Ruby 赋值运算符:
1. x = “hello”:
x ------> “hello”
2. y = x:
x ------> “hello”
^
|
y -----------+
3. y << “ world”:
x ------> “hello world”
^ ^
| ^
y -----------+ ^
> > >
x 和 y 的名字可能拼写为 @name
和 @@current_name
并不重要。
这是另一个代码示例:
x = "hello"
y = x
y << " world"
puts x, y
--output:--
hello world
hello world
x.next!
puts x, y
--output:--
hello worle
hello worle
这里有一个 immutable types
的例子:
1. x = 10:
x ------> 10
2. y = x:
x ---------> 10
^
|
y -----------+
3. y += 1
=> y = y + 1
=> y = 10 + 1
And 10 + 1 creates the new Integer object 11 and assigns it to y:
x ------> 10
y ------> 11
表达式 10 + 1
不会递增 x 和 y 都引用的整数对象 10 -- 因为整数对象是不可变的。
这是另一个例子:
x = 10
y = x
x.next
puts x,y #=> ??
x.next新建一个Integer对象11,由于新建的Integer对象11没有赋值给变量,11被丢弃,所以x和y仍然引用同一个Integer对象10。
我创建了一个 class 为每个实例生成不同的名称,但是在一个语句中实例化两个实例时测试意外失败。
这里是 class.
class Robot
attr_accessor :name
@@current_name = 'AA000'
def initialize
@name = @@current_name
@@current_name.next!
end
end
此处 class 的行为符合预期
irb(main):009:0> Robot.new.name
=> "AA001"
irb(main):010:0> Robot.new.name
=> "AA002"
这是意想不到的行为,我期待 false
。此代码正在对我试图通过的练习进行测试,因此我无法更改测试。
irb(main):011:0> Robot.new.name == Robot.new.name
=> true
检查 object_id
显示正在创建两个不同的实例。
irb(main):012:0> Robot.new.object_id == Robot.new.object_id
=> false
为什么 Ruby 这样做,我应该如何修复它 & 假设有一个术语,我可以在搜索中输入什么来找到关于这个问题的答案。
看看这是否有帮助:
class Robot
attr_accessor :name
@@current_name = 'AA000'
def initialize
@name = @@current_name
@@current_name.next!
end
end
x = Robot.new
puts x.name
y = Robot.new
puts y.name
puts x.name == y.name
puts x.name
puts y.name
--output:--
AA001
AA002
true
AA002
AA002
Why is Ruby doing this
因为每个实例的 @name
变量引用与变量 @@current_name
相同的字符串,并且您不断使用 !
方法更改该字符串。
what should I do to fix it
class Robot
attr_accessor :name
@@current_name = 'AA000'
def initialize
@name = @@current_name.dup
@@current_name.next!
end
end
x = Robot.new
puts x.name
y = Robot.new
puts y.name
p x.name == y.name
p x.name
p y.name
--output:--
AA000
AA001
false
AA000
AA001
尽管如此,我和许多其他人会警告您永远不要在代码中使用 @@variables
。
Ruby 赋值运算符:
1. x = “hello”:
x ------> “hello”
2. y = x:
x ------> “hello”
^
|
y -----------+
3. y << “ world”:
x ------> “hello world”
^ ^
| ^
y -----------+ ^
> > >
x 和 y 的名字可能拼写为 @name
和 @@current_name
并不重要。
这是另一个代码示例:
x = "hello"
y = x
y << " world"
puts x, y
--output:--
hello world
hello world
x.next!
puts x, y
--output:--
hello worle
hello worle
这里有一个 immutable types
的例子:
1. x = 10:
x ------> 10
2. y = x:
x ---------> 10
^
|
y -----------+
3. y += 1
=> y = y + 1
=> y = 10 + 1
And 10 + 1 creates the new Integer object 11 and assigns it to y:
x ------> 10
y ------> 11
表达式 10 + 1
不会递增 x 和 y 都引用的整数对象 10 -- 因为整数对象是不可变的。
这是另一个例子:
x = 10
y = x
x.next
puts x,y #=> ??
x.next新建一个Integer对象11,由于新建的Integer对象11没有赋值给变量,11被丢弃,所以x和y仍然引用同一个Integer对象10。