Дело 1
class A
def initialize(x,y)
@x = x
@y = y
end
def m
@x = 5
@y = 6
end
end
a1 = A.new(1,2)
#=> #<A:0x00005d22a3878048 @x=1, @y=2>
a1.m
a1 #=> #<A:0x00005d22a3878048 @x=5, @y=6>
a2 = A.new(3,4)
#=> #<A:0x00005d22a38b5330 @x=3, @y=4>
a2.m
a2 #=> #<A:0x00005d22a38b5330 @x=5, @y=6>
Затем
a1.instance_variables.all? { |e|
a1.instance_variable_get(e) == a2.instance_variable_get(e) }
#=> true
говорит нам, что значения @x
и значения @y
одинаковы для обоих экземпляров.
Случай 2
Теперь давайте изменим код, чтобы условно добавить еще одну переменную экземпляра.
class A
def initialize(x,y)
@x = x
@y = y
end
def m
@z = 3 if @x == 3
@x = 5
@y = 6
end
end
a1 = A.new(1,2)
#=> #<A:0x000057d1fd563c78 @x=1, @y=2>
a1.m
a1 #=> #<A:0x000057d1fd27f200 @x=5, @y=6>
a2 = A.new(3,4)
#=> #<A:0x000057d1fd57cb38 @x=3, @y=4>
a2.m
a2 #=> #<A:0x000057d1fd2f9e10 @x=5, @y=6, @z=3>
В этот момент все переменные экземпляра одного из этих экземпляров равны соответствующей переменной экземпляра другого экземпляра? Нет, потому что a2
имеет дополнительную переменную экземпляра, @z
. Поэтому
a1.instance_variables.all? { |e|
a1.instance_variable_get(e) == a2.instance_variable_get(e) }
#=> true
дает неправильный ответ по понятным причинам. Возможно, мы могли бы проверить это следующим образом:
a1.instance_variables.all? { |e|
a1.instance_variable_get(e) == a2.instance_variable_get(e) } &&
a2.instance_variables.all? { |e|
a1.instance_variable_get(e) == a2.instance_variable_get(e) }
#=> true && false => false
Это имеет значение, однако, если @z
равно nil
.
Случай 3
class A
def initialize(x,y)
@x = x
@y = y
end
def m
@z = nil if @x == 3
@x = 5
@y = 6
end
end
a1 = A.new(1,2)
#=> #<A:0x000057d1fd2d18e8 @x=1, @y=2>
a1.m
a1 #=> #<A:0x000057d1fd2d18e8 @x=5, @y=6>
a2 = A.new(3,4)
#=> #<A:0x000057d1fd46b460 @x=3, @y=4>
a2.m
a2
#=> #<A:0x000057d1fd46b460 @x=5, @y=6, @z=nil>
a1.instance_variables.all? { |e|
a1.instance_variable_get(e) == a2.instance_variable_get(e) } &&
a2.instance_variables.all? { |e|
a1.instance_variable_get(e) == a2.instance_variable_get(e) }
#=> true && true => true
Мы получаем этот неверный результат, потому что:
class A
end
A.new.instance_variable_get(:@z)
#=> nil
Поэтому мы должны подтвердить, что если один экземпляр имеет переменную экземпляра с именем e
, то же самое относится и к другому экземпляру, и что каждая пара переменных экземпляра с одинаковым именем равны. Один из способов сделать это заключается в следующем:
(a1.instance_variables.sort == a2.instance_variables.sort) &&
a1.instance_variables.all? { |e|
a1.instance_variable_get(e) == a2.instance_variable_get(e) }
#=> false && true => false
См. Enumerable # all? , Object # instance_variables и Object # instance_variable_get .