1
class PassByValueScopeConfusion

  def does_not_modify(s)
    s = "DIFFERENT"
  end

  def does_modify(s)
    s.upcase!
  end

end

obj = PassByValueScopeConfusion.new

some_string = "abcdefg"

# does not change the value of some_string
obj.does_not_modify(some_string)

# changes the value of some_string
obj.does_modify(some_string)

渡された文字列で破壊的なメソッドを呼び出すメソッドに文字列を渡していますが、どういうわけか、元の変数「some_string」が変更されています。破壊的なメソッドを使用してスコープ外の「some_string」変数を変更できる場合、代入演算子を使用してそれを行う方法はありますか (replace メソッドを呼び出す以外に)?

編集代入演算子で許可されていない場合、Rubyは破壊演算子でスコープ外の変数を変更できるのはなぜですか?

4

3 に答える 3

1

この 2 つのケースには違いがあります。

s.upcase!

これは、「参照 s が指しているオブジェクトの状態を変更する」ことを意味します。

s = "DIFFERENT"

一方、これは「オブジェクトへの参照を作成して、完全に異なるオブジェクトを指し示す」(または、必要に応じて「名前を別のオブジェクトにバインドする」) ことを意味します。souter をシャドウする新しいオブジェクトが作成されますs。この方法で外部オブジェクトを変更する方法はありません。

于 2013-02-13T06:31:00.183 に答える
0

文字列オブジェクトを指す参照を渡します。

したがって、does_not_modifyの例では、呼び出されると、sには文字列「abcdefg」を含むメモリアドレスへのポインタが含まれます。次に、参照の値を変更して、新しい文字列「DIFFERENT」を保持するメモリ内の新しい別の場所を指すようにします。ただし、呼び出し元のコードは、元の文字列「abcdefg」の元の場所を引き続き指します。

does_modifyの例では、sには、文字列「abcdefg」を含むメモリアドレスへのポインタが含まれています。upcase関数は、メモリのこの部分を直接変更し、各文字を「ABCDEFG」に変更します。呼び出し元のコードはこの同じメモリアドレスを指しているため、関数が戻った後も変更は保持されます。

于 2013-02-13T06:38:39.127 に答える
0

Ruby がスコープ外の変数の変更を許可するのはなぜですか?

そうではありません。変数を変更するのではなく、変数が指すオブジェクトを変更しています。

于 2013-02-13T11:42:58.830 に答える