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?

Foi útil?

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top