Pergunta
Eu esperava o seguinte código para imprimir "8", "111" e "999". I supor que cada um, b, c e d pontos para o mesmo local de memória. Se eu alterar o local através de um deles, por que o outro não à mudança? Claramente, a minha lógica é pobre, ou eu esperasse algo. Ela imprime "7", "7" e "8", em vez disso.
Por quê?
a=b=c=d=7
b = 8
puts d
c = 111
puts a
d = 999
puts b
[Esclarecimento]
A razão para a minha confusão é o exemplo em o livro (página 20). eles mudam há semelhante os valores, mas eles obter os resultados que eu sugeri acima. Estamos falando do mesmo assunto?
Solução
a=b=c=d=7
# a, b, c and d points to the same integer object "7"
b = 8
# b now points to a new object "8"
# "=" does not change the value of the pointer integer,
# it assings a new reference like in the line above
puts d
# obviously, d still points to "7"
c = 111
# c now points to another integer object "111"
puts a
# a still points to "7"
d = 999
# d now points to a new integer object "999"
puts b
# b still points to "8"
em Ruby, o objeto Integer é imutável para que você não pode atribuir um número inteiro de referência múltiplas e alterar o seu valor depois.
Como @pts sugerido, você deve usar uma matriz para embrulhar sua referência Integer porque Arrays são mutáveis ??para você é capaz de alterar o valor depois.
a=b=c=d=[7]
b[0] = 8
puts d[0]
c[0] = 111
puts a[0]
d[0] = 999
puts b[0]
ESCLARECIMENTO:
Se você vem de um fundo C ++, pode ser estranho, porque C ++ faz 2 coisas com a mesma sintaxe, atribuindo a referência e alterando o valor referenciado.
int a = 10; // creates an int on the stack with value 10
int& b = a; // creates a reference to an int and references the a variable
b = 5; // change the value referenced by b (so a) to 5
// a and b now hold the value 5
Em Ruby, referência são mutáveis ??e inteiros não são (exatamente o contrário do C ++). Assim, a atribuição de uma referência vai realmente mudar a referência e não o valor referenciado.
Outra solução seria a criação de uma classe que é um número inteiro mutável:
class MutableInteger
attr_writer :value
def initialize(value)
@value = value
end
def inspect
value
end
def to_i
value
end
def to_s
value
end
end
a = b = MutableInteger.new(10)
a.value = 5
puts b
# prints 5
Outras dicas
A maneira mais fácil para obter o resultado que você espera está usando uma matriz de elemento único:
a=b=c=d=[7]
b[0] = 8
puts d[0]
c[0] = 111
puts a[0]
d[0] = 999
puts b[0]
Para obter se a e b se referem ao mesmo objeto, o uso a.__id__ == b.__id__
.
Eles não apontam para o mesmo local de memória. Ruby não passar por referência .
Depois da primeira linha, a, b, c e d, todas apontam para o mesmo objecto Fixnum (com o valor 7). No entanto, quando você executar b = 8, b aponta agora para um novo objeto Fixnum (com valor 8).
Efetivamente você está atribuindo b para um novo objeto, ao invés de mutação do objeto existente. É por isso que suas alterações não estão sendo propagadas como você esperava.
Se você está comparando com C ++, isto é como a atribuição de um ponteiro por valor, em vez de atribuir por referência.
Eu recomendo fortemente a leitura C passa Java referência e ruby ??não