Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

Ruby Freeze 방법 – 객체 변경 가능성 이해하기

개체가 변경 가능하다는 것은 무엇을 의미합니까?

"가변성 "는 객체의 내부 상태가 변경될 수 있음을 의미합니다. 이것은 고정된 개체를 제외한 모든 개체의 기본값입니다. , 또는 특수 개체 목록의 일부인 개체입니다.

즉, Ruby의 모든 객체가 변경 가능한 것은 아닙니다!

예를 들어 :

숫자나 기호, 심지어 true에도 의미가 없습니다. 또는 false (또한 객체이기도 함) 변경할 수 있습니다.

숫자 1은 항상 1이 됩니다.

그러나 다른 개체, 특히 Array 또는 Hash 개체와 같이 데이터를 저장하는 개체는 성능상의 이유로 변경할 수 있는 기능이 있어야 합니다.

대안은 무엇입니까?

새 사본을 만들 수 있습니다. 변경 사항이 있는 개체를 변경한 다음 원래 개체를 그대로 두고 이 새 개체를 반환합니다.

배열이 불변인 경우 배열의 한 요소만 변경하려면 변경되지 않은 요소를 포함하여 모든 데이터를 복사해야 합니다.

아무리 작은 것이라도 변경해야 할 때마다 100만(또는 그 이상) 요소 배열을 복사해야 한다고 상상해보세요! 그다지 효율적이지 않습니다...

어쨌든.

Ruby에서 가변성이 어떻게 작동하는지 조금 더 자세히 살펴보겠습니다.

포인터로서의 가변성과 변수

다음 두 가지 조합으로 인해 발생하는 프로그래밍 오류 범주가 있습니다.

  • 변경 가능한 개체.
  • 변수에는 데이터가 직접 포함되지 않고 이 데이터가 저장되는 위치에 대한 참조가 포함된다는 사실

이러한 오류가 표시되는 한 가지 방법은 변수에 '별칭'을 지정하려고 할 때입니다.

예시입니다 :

name       = "Peter"
other_name = name

puts other_name
# "Peter"

이 예에서 nameother_name 동일한 문자열 개체에 대한 참조를 포함합니다. 이 문자열의 내용을 표시하거나 수정하는 데 사용할 수 있습니다.

Ruby Freeze 방법 – 객체 변경 가능성 이해하기

other_name을(를) 처리하면 문제가 나타납니다. 문자열의 복사본과 같습니다.

other_name[0] = 'T'

name       # "Teter"
other_name # "Teter"

두 변수가 동일한 문자열을 가리키기 때문에 "Peter"를 "Teter"로 변경했습니다. "Peter"를 주변에 두려고 했기 때문에 문제가 되는 것입니다.

개체 복제

이 문제를 처리하는 한 가지 방법은 dup을 사용하는 것입니다. 방법.

이것은 Ruby에게 객체의 사본을 제공하도록 지시할 것입니다. clone도 있습니다. 이 메서드는 개체 복사본을 제공할 뿐만 아니라 개체에 정의된 고정 상태 및 단일 메서드를 복사합니다.

예시를 보자 :

numbers = [1, 2, 3]

more_numbers = numbers.dup
more_numbers << 4

numbers      # [1, 2, 3]
more_numbers # [1, 2, 3, 4]

이 예에서 원본 numbers가 어떻게 배열은 변경되지 않았습니다. 해당 dup을 제거해 보세요. 세 번째 라인에 전화해서 무슨 일이 일어나는지 보세요 🙂

루비 동결 방법

개체를 원치 않는 변경으로부터 안전하게 유지하는 또 다른 방법은 개체를 '고정'하는 것입니다. 모든 Ruby 객체는 freeze를 사용하여 고정할 수 있습니다. 방법.

개체가 고정되면 이 개체를 변경하려고 하면 RuntimeError가 발생합니다. 예외.

<블록 인용>

참고:frozen?을 사용할 수 있습니다. 개체가 고정되었는지 여부를 확인하는 메서드입니다.

:

animals = %w( cat dog tiger )
animals.freeze

animals << 'monkey'
# RuntimeError: can't modify frozen Array

한 가지 명심해야 할 점은 이 예제에서는 하나의 객체만 고정된다는 것입니다. 이 예제에서는 배열 자체에서 항목을 추가하거나 제거할 수 없습니다. 그러나 배열 내부의 문자열은 고정되지 않으므로 계속 변경할 수 있습니다. !

animals[1][0] = 't'
# => ["cat", "tog", "tiger"]

문자열을 고정하려면 freeze를 호출해야 합니다. 그들에. 다음과 같이:animals.each(&:freeze) .

고정 문자열

변경 가능한 객체는 성능, 특히 문자열에도 영향을 미칩니다. 그 이유는 큰 프로그램에서 동일한 문자열이 여러 번 사용될 가능성이 높기 때문입니다.

Ruby는 두 문자열이 동일하게 보이거나 다시 말해 동일한 '내용'이 있더라도 모든 문자열에 대해 새 객체를 생성합니다. irb에서 이런 일이 일어나는 것을 쉽게 볼 수 있습니다. object_id를 사용하는 경우 방법.

예시입니다 :

a = 'test'
b = 'test'

a.object_id # 76325640
b.object_id # 76317550

이러한 개체가 추가 메모리와 추가 CPU 주기를 소비하기 때문에 문제가 됩니다.

Ruby 2.1부터 고정 문자열을 사용할 때 , Ruby는 동일한 문자열 객체를 사용합니다. 이렇게 하면 동일한 문자열의 새 복사본을 만들 필요가 없습니다. 그 결과 메모리가 약간 절약되고 성능이 약간 향상됩니다.

Rails는 광범위함을 만듭니다. 이러한 이유로 고정 문자열을 사용합니다. 예를 들어, 이 PR을 살펴보십시오.

이로 인해 Ruby 개발 팀은 문자열을 불변으로 이동하는 것을 고려하기 시작했습니다. 기본적으로 개체. 사실, 며칠 전에 출시된 Ruby 2.3에는 프로젝트에서 이를 활성화하는 두 가지 방법이 포함되어 있습니다.

하나는 # frozen_string_literal: true를 포함하는 것입니다. 문자열을 변경할 수 없도록 하려는 모든 파일의 맨 위에 있습니다. 다른 하나는 명령줄 인수 --enable=frozen-string-literal를 사용하는 것입니다. .

기본적으로 변경할 수 없는 문자열은 Ruby 3.0에 포함될 것입니다.

이제 미쳐서 앱의 모든 문자열을 고정하지 마십시오. 일종의 이점을 보기 위해 수백 번 사용되는 문자열에 대해서만 이 작업을 수행하려고 합니다. . 하지만 다음은 잠재적인 문자열을 고정하는 데 사용할 수 있는 도구입니다.

방법 알기

변경 가능한 객체의 모든 메소드가 실제로 객체를 변경하는 것은 아닙니다. 예를 들어, gsub 메소드는 원본을 건드리지 않고 새 문자열을 반환합니다.

이러한 방법 중 일부에는 대체 버전이 있습니다. 이는 원래 개체를 제자리에서 변경하므로 종종 더 효율적입니다. 이러한 메서드는 종종 느낌표 !로 끝납니다. 효과를 나타냅니다.

이러한 'bang' 메서드의 두 가지 예는 gsub!입니다. 및 map! .

참고 :

!로 끝나는 메소드 항상 '객체를 변경하는 메서드'를 의미하지는 않습니다.

보다 일반적인 용어로 ! 기호는 '위험'을 나타내는 데 사용됩니다. 하나의 이것은 exit!입니다. 이 메서드는 종료 처리기를 무시하고 프로그램을 즉시 종료합니다.

객체를 변경하고 !로 끝나지 않는 메소드도 있습니다. 상징. 예:delete , clear , push , concat 등이 있습니다.

마무리

가변성은 까다로운 주제일 수 있지만 이 게시물을 읽은 이후로 이제 이를 다룰 준비가 훨씬 더 잘 된 것입니다. 메서드가 무엇을 하는지 잘 모르는 경우 Ruby 문서를 확인하세요. 문제를 방지하는 데 도움이 됩니다.

이 기사가 유익한 정보가 되었기를 바랍니다. 공유하세요. 친구들과 함께 즐길 수 그것도. 또한 아래 뉴스레터에 가입하여 이와 같은 콘텐츠가 나올 때 더 이상 놓치지 않도록 하세요!