Por que a ausência do operador de atribuição me permite modificar uma constante rubi sem aviso do compilador?
-
21-08-2019 - |
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?
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 .