2009-03-21 11 views
4

다음 두 예제에서 나는 상수 String을 만들고 concat 메서드를 사용하여 수정했습니다. 그것은 상수이기 때문에 컴파일러 경고를 기대하지만 할당 연산자를 사용할 때 두 번째 예제에서 하나만받습니다. 왜 이런거야? 의 할당은 연산자를 사용할 필요가 없습니다 때문에 CONCAT 방법부터왜 할당 연산자가 없어 컴파일러 경고없이 루비 상수를 수정할 수 있습니까?

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

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

, 즉 내가 무엇을 할 것이라고 일반적이다, 장소에 문자열을 수정합니다. 그렇다면 할당 연산자의 존재로 인해 컴파일러는이 두 연산을 다른 것으로 식별하게되는 이유는 무엇입니까?

+0

엄밀히 말하면 컴파일러 경고가 아닌 인터프리터 경고입니다. 루비는 일반적으로 컴파일되지 않습니다. –

답변

6

이것은 새로운 X를 재정의하기 때문에 발생합니다. 상수를 재정의하면 "이미 초기화 됨"오류가 발생합니다. 첫 번째 예제는 X를 재정의하지 않았기 때문에이 오류를 표시하지 않고 수정합니다.

+1

오른쪽의 루비 상수는 변경할 수 없으며 객체를 전환하지 않는다는 의미입니다. – rampion

7

루비에서 변수는 본질적으로 객체를 포함하는 메모리에있는 장소의 포인터입니다. 객체 자체는 아닙니다. 두 번째 예제에서는 상수 X을 초기화하여 첫 번째 행 (X = "hello")의 객체를 가리키고 두 번째 행에서 상수를 다시 초기화하지만 이미 객체를 가리키고 있으므로 객체를 가져옵니다. 오류.

상수의 불변성은 개체를 변경할 수 없다는 것을 의미하지 않으며 단지 또 다른 개체를 가리 키도록 상수를 변경할 수 없다는 것을 의미합니다.

0

상수 XString 개체에 대한 참조를 저장하고 있기 때문입니다. 첫 번째 예제에서는 String 개체의 내부 상태를 수정하지만 상수에 의해 저장된 참조는 수정하지 않습니다. 두 번째 예에서는 상수로 저장된 참조를 concat 메서드에서 반환되는 새 String 개체로 변경합니다.

PickAxe 책에 대한 설명은 here입니다. 당신이 당신의 문자열이 "진짜"일정하게 '동결'을 시도하려는 경우

4

:

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

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

은 정말 The Ruby Programming Languge을 읽어 보시기 바랍니다.

+0

책에 대한 링크를 제공해 주셔서 감사합니다. Safari 책꽂이에 책을 추가했습니다. –

+0

"이상한"루비 코너를 이해하는 데 도움이 될 것입니다 (적어도 C++/Java 프로그래머에게는). "Ruby Hacking Guide"(http://rhg.rubyforge.org/)는 특히 Ruby 메타 프로그래밍이 어떻게 작동 하는지를 이해하고자 할 때 아주 좋은 곳입니다. –