Por que a ausência do operador de atribuição me permite modificar uma constante rubi sem aviso do compilador?

StackOverflow https://stackoverflow.com/questions/670094

Pergunta

Nos dois exemplos a seguir eu faço a mesma coisa, criando uma constante de Cordas e usando o método concat para modificá-lo. Porque é uma constante, espero um aviso do compilador, mas apenas receber uma no segundo exemplo, quando eu usar o operador de atribuição. Por que isso?

X = "hello"
X.concat(" world")
puts X # no warning

X = "hello"
X = X.concat(" world")
puts X # warning: already initialized

Uma vez que os modifica método concat a corda no lugar, que é normalmente o que eu faria, já que não há necessidade de usar um operador assigment. Então, por que a presença do operador de atribuição causa o compilador para identificar essas duas operações como sendo diferente?

Foi útil?

Solução

Este é porque você está re-definindo um novo X. Quando você redefinir uma constante que lhe dá o erro "já inicializado". O primeiro exemplo não dá este erro porque você não está redefinindo X, você está modificando-o.

Outras dicas

Em Ruby, variáveis ??são essencialmente ponteiros para um lugar em uma memória contendo um objeto - não o próprio objeto. No segundo exemplo, você está inicializando um X constante para apontar para um objeto na primeira linha (X = "hello"), e na segunda linha, você está novamente inicializar o constante - mas já aponta para um objeto, de modo a obter o erro.

imutabilidade de uma constante não significa que você não pode alterar o objeto -. Isso significa apenas que você não pode mudar a constante para apontar para outro objeto

Se você quiser fazer sua string constante "real", tente 'congelar':

X = "foo".freeze        # => "foo" 
X.concat("bar")

TypeError: can't modify frozen string
    from (irb):2:in `concat'
    from (irb):2

Eu realmente encorajo-vos a ler The Ruby Programming Languge .

Isto é porque o X constante é armazenando uma referência a um objecto String. Em seu primeiro exemplo, você está modificando o estado interno do objeto String, mas não a referência armazenada pela constante. No segundo exemplo, você está mudando a referência armazenada pela constante a um novo objeto String que é retornado do método concat.

O livro picareta explica esta aqui .

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