なぜ代入演算子の不在はありませんコンパイラの警告とRubyの定数を変更するために私を許可していますか?
-
21-08-2019 - |
質問
次の2つの例では、私は一定の文字列を作成し、それを修正するためにconcatメソッドを使用して、同じことを行います。それは定数なので、私は、コンパイラの警告を期待するが、私は代入演算子を使用する場合のみ、第二の例では1を受け取ります。これはなぜでしょうか?
X = "hello"
X.concat(" world")
puts X # no warning
X = "hello"
X = X.concat(" world")
puts X # warning: already initialized
assigment演算子を使用する必要はありませんので、concatメソッドは、代わりに文字列を変更しているので、それは通常の私は、どうなるのか。それでは、なぜ代入演算子の存在は、コンパイラが異なっているように、これらの2つの操作を特定するようにしますか?
解決
これは、あなたがしているので、あなたはそれがあなたに「すでに初期化」エラーを与える定数を再定義新しいXを再定義しています。あなたはそれを修正している、Xを再定義していないので、最初の例では、このエラーを与えるものではありません。
他のヒント
Rubyでは、変数は、本質的にオブジェクトを含むメモリ内の場所へのポインタです。第二の例では、最初の行(X
)内のオブジェクトを指すように定数X = "hello"
を初期化され、2行目には、再度、一定の初期化されている - が、あなたが得るように、それは既に、オブジェクトを指し示しますエラーます。
定数の不変性は、あなたがオブジェクトを変更することはできませんという意味ではありません - それはちょうどあなたがの他のオブジェクトを指すように定数を変更することができないことを意味します。
。あなたが一定のあなたの文字列が「本物」にしたい場合は、「凍結」を試してください:
X = "foo".freeze # => "foo"
X.concat("bar")
TypeError: can't modify frozen string
from (irb):2:in `concat'
from (irb):2
私は本当にのRubyプログラミングLanguge を読むことをお勧めします。
定数X
がString
オブジェクトへの参照を記憶しているためです。あなたの最初の例では、String
オブジェクトの内部状態を変更しているが、参照が定数で保存されません。第二の例では、String
メソッドから返された新しいconcat
オブジェクトに定数によって記憶された基準を変更している。
つるはしブックはこちらのこのを説明します。