문제

불변성에 관한 몇 가지 기사를 읽었지만 여전히 개념을 잘 따르지 않습니다.

나는 최근에 여기에 불변성을 언급한 스레드를 만들었습니다. 그러나 이 주제 자체가 주제이기 때문에 지금은 전용 스레드를 만들고 있습니다.

지난 스레드에서 불변성은 객체를 읽기 전용으로 만들고 가시성을 낮추는 프로세스라고 생각했다고 언급했습니다.다른 회원은 그 일과 전혀 관련이 없다고 말했습니다. 이 페이지 (의 일부 시리즈)은 불변 클래스/구조체의 예를 사용하고 읽기 전용 및 기타 개념을 사용하여 이를 잠급니다.

이 예의 경우 상태의 정의는 정확히 무엇입니까?상태는 내가 실제로 이해하지 못한 개념입니다.

디자인 지침 관점에서 볼 때 불변 클래스는 사용자 입력을 허용하지 않고 실제로 값만 반환하는 클래스여야 합니다.

제가 이해한 바로는 정보를 반환하는 모든 개체는 변경이 불가능하고 "잠겨" 있어야 합니다. 그렇죠?따라서 해당 메서드를 사용하여 전용 클래스에서 현재 시간을 반환하려면 참조 유형을 사용해야 합니다. 참조 유형은 해당 유형의 참조로 작동하므로 불변성의 이점을 얻을 수 있습니다.

도움이 되었습니까?

해결책

불변성이란 무엇입니까?

  • 불변성은 주로 물체 (문자열, 어레이, 커스텀 동물 클래스)에 적용됩니다.
  • 일반적으로 불변의 클래스 버전이있는 경우 변동 가능한 버전도 사용할 수 있습니다. 예를 들어, Objective-C와 Cocoa는 NSString 클래스 (불변)와 NSMutableString 클래스를 모두 정의합니다.
  • 객체가 불변 인 경우 (기본적으로 읽기 전용) 생성 된 후에는 변경할 수 없습니다. "생성자 만 객체를 변경할 수 있습니다"라고 생각할 수 있습니다.

이것은 사용자 입력과 직접 관련이 없습니다. 코드조차도 불변의 물체의 가치를 변경할 수 없습니다. 그러나 항상 새로운 불변의 물체를 만들어 교체 할 수 있습니다. 여기 유사 코드 예는 다음과 같습니다. 많은 언어로 단순히 할 수 있습니다 myString = "hello"; 아래에서와 같이 생성자를 사용하는 대신 명확성을 위해 포함 시켰습니다.

String myString = new ImmutableString("hello");
myString.appendString(" world"); // Can't do this
myString.setValue("hello world"); // Can't do this
myString = new ImmutableString("hello world"); // OK

"정보를 반환하는 객체"를 언급합니다. 이것은 자동적으로 불변성에 대한 좋은 후보가되지 않습니다. 불변의 물체는 항상 구축 된 것과 동일한 값을 반환하는 경향이 있으므로 현재 시간이 자주 변경되기 때문에 현재 시간이 이상적이지 않다고 말하는 경향이 있습니다. 그러나 특정 타임 스탬프로 작성된 MomentOftime 클래스를 가질 수 있으며 앞으로 항상 하나의 타임 스탬프를 반환합니다.

불변의 이점

  • 객체를 다른 함수/메소드로 전달하는 경우 함수가 반환 된 후 해당 객체가 동일한 값을 갖는지 걱정할 필요가 없습니다. 예를 들어:

    String myString = "HeLLo WoRLd";
    String lowercasedString = lowercase(myString);
    print myString + " was converted to " + lowercasedString;
    

    구현이면 어떻게해야합니까? lowercase() 소문자 버전을 만들면서 MyString을 변경 했습니까? 세 번째 줄은 당신이 원하는 결과를주지 않을 것입니다. 물론, 좋은 lowercase() 기능은 이것을 수행하지 않지만 MyString이 불변이라면이 사실을 보장합니다. 따라서 불변의 물체는 우수한 객체 지향 프로그래밍 관행을 시행하는 데 도움이 될 수 있습니다.

  • 불변의 객체 스레드 안전을 만드는 것이 더 쉽습니다

  • 그것은 잠재적으로 클래스의 구현을 단순화 할 수 있습니다 (수업을 작성하는 사람이라면 좋음).

상태

객체의 모든 인스턴스 변수를 가져 와서 종이에 값을 적어두면 주어진 순간에 그 객체의 상태가 될 것입니다. 프로그램의 상태는 주어진 순간에 모든 객체의 상태입니다. 상태는 시간이 지남에 따라 빠르게 변화합니다. 계속 실행하려면 프로그램이 상태를 변경해야합니다.

그러나 불변의 물체는 시간이 지남에 따라 고정 상태를 가지고 있습니다. 일단 생성되면, 불변의 객체의 상태는 프로그램의 상태가 전체적으로 변경되지 않지만 변하지 않습니다. 이를 통해 일어나는 일을 쉽게 추적 할 수 있습니다 (위의 다른 이점을 참조하십시오).

다른 팁

불변성

간단히 말해서 메모리는 초기화 후 수정되지 않으면 변경할 수 없습니다.

C, Java 및 C#과 같은 명령형 언어로 작성된 프로그램은 메모리 내 데이터를 마음대로 조작할 수 있습니다.일단 따로 확보된 물리적 메모리 영역은 프로그램 실행 중 언제든지 실행 스레드에 의해 전체 또는 부분적으로 수정될 수 있습니다.실제로 명령형 언어는 이러한 프로그래밍 방식을 권장합니다.

이러한 방식으로 프로그램을 작성하면 단일 스레드 응용 프로그램에서 매우 성공적이었습니다.그러나 최신 애플리케이션 개발이 단일 프로세스 내에서 여러 동시 작업 스레드로 이동함에 따라 잠재적인 문제와 복잡성의 세계가 도입되었습니다.

실행 스레드가 하나만 있는 경우 이 단일 스레드가 메모리의 모든 데이터를 '소유'하므로 마음대로 조작할 수 있다고 상상할 수 있습니다.그러나 여러 실행 스레드가 관련된 경우 암시적인 소유권 개념이 없습니다.

대신, 이 부담은 모든 판독기에 대해 메모리 내 구조가 일관된 상태인지 확인하기 위해 많은 노력을 기울여야 하는 프로그래머의 몫입니다.다른 스레드에 의해 업데이트되는 동안 한 스레드가 데이터를 볼 수 없도록 잠금 구성을 신중하게 사용해야 합니다.이러한 조정이 없으면 스레드는 필연적으로 업데이트가 절반만 진행된 데이터를 소비하게 됩니다.그러한 상황의 결과는 예측할 수 없으며 종종 재앙적입니다.더욱이 코드에서 잠금 작업을 올바르게 수행하는 것은 악명이 높으며 잘못 수행할 경우 성능이 저하될 수 있으며 최악의 경우 실행이 복구 불가능하게 중단되는 교착 상태가 발생할 수 있습니다.

불변 데이터 구조를 사용하면 코드에 복잡한 잠금을 도입할 필요성이 줄어듭니다.프로그램 수명 동안 메모리 섹션이 변경되지 않는 것이 보장되면 여러 판독기가 동시에 메모리에 액세스할 수 있습니다.일관성이 없는 상태에서는 특정 데이터를 관찰하는 것이 불가능합니다.

Lisp, Haskell, Erlang, F# 및 Clojure와 같은 많은 함수형 프로그래밍 언어는 본질적으로 불변 데이터 구조를 권장합니다.점점 복잡해지는 멀티스레드 애플리케이션 개발과 다수의 컴퓨터 컴퓨터 아키텍처로 나아가면서 이에 대한 관심이 다시 부각되고 있는 것도 바로 이러한 이유 때문입니다.

상태

애플리케이션의 상태는 주어진 시점의 모든 메모리 및 CPU 레지스터의 내용으로 간단히 생각할 수 있습니다.

논리적으로 프로그램의 상태는 두 가지로 나눌 수 있습니다.

  1. 힙의 상태
  2. 각 실행 스레드의 스택 상태

C# 및 Java와 같은 관리되는 환경에서는 한 스레드가 다른 스레드의 메모리에 액세스할 수 없습니다.따라서 각 스레드는 스택 상태를 '소유'합니다.스택은 지역 변수와 값 유형의 매개변수를 보유하는 것으로 생각할 수 있습니다(struct) 및 개체에 대한 참조입니다.이러한 값은 외부 스레드로부터 격리됩니다.

그러나 힙의 데이터는 모든 스레드 간에 공유 가능하므로 동시 액세스를 제어하는 ​​데 주의를 기울여야 합니다.모든 참조 유형(class) 객체 인스턴스는 힙에 저장됩니다.

OOP에서 클래스 인스턴스의 상태는 해당 필드에 의해 결정됩니다.이러한 필드는 힙에 저장되므로 모든 스레드에서 액세스할 수 있습니다.클래스가 생성자가 완료된 후 필드를 수정할 수 있는 메서드를 정의하는 경우 클래스는 변경 가능합니다(불변 아님).어떤 방식으로든 필드를 변경할 수 없는 경우 유형은 변경할 수 없습니다.모든 C#이 포함된 클래스라는 점에 유의하는 것이 중요합니다. readonly/자바 final 필드가 반드시 변경 불가능한 것은 아닙니다.이러한 구성은 다음을 보장합니다. 참조 변경할 수 없지만 참조된 개체는 변경할 수 없습니다.예를 들어 필드에는 개체 목록에 대한 변경 불가능한 참조가 있을 수 있지만 목록의 실제 내용은 언제든지 수정될 수 있습니다.

유형을 실제로 불변으로 정의하면 해당 상태가 고정된 것으로 간주될 수 있으므로 해당 유형은 여러 스레드에서 액세스해도 안전합니다.

실제로 모든 유형을 불변으로 정의하는 것은 불편할 수 있습니다.불변 유형의 값을 수정하려면 상당한 양의 메모리 복사가 필요할 수 있습니다.일부 언어는 이 프로세스를 다른 언어보다 쉽게 ​​만들지만 어느 쪽이든 CPU가 추가 작업을 수행하게 됩니다.메모리 복사에 소요된 시간이 잠금 경합의 영향보다 큰지 여부를 결정하는 데에는 여러 가지 요소가 영향을 미칩니다.

목록이나 트리와 같은 불변 데이터 구조의 개발에 대한 많은 연구가 진행되었습니다.목록과 같은 구조를 사용할 때 '추가' 작업은 새 항목이 추가된 새 목록에 대한 참조를 반환합니다.이전 목록에 대한 참조에는 어떠한 변경 사항도 표시되지 않으며 여전히 일관된 데이터 보기를 갖습니다.

간단하게 말하면 : 불변의 물체를 만들면 해당 객체의 내용을 변경할 수있는 방법이 없습니다. .NET 불변의 객체의 예는 String과 Uri입니다.

문자열을 수정하면 새 문자열을 얻습니다. 원래 문자열은 변경되지 않습니다. URI에는 재고 속성 만 가지고 있으며 URI의 내용을 변경할 수있는 방법이 없습니다.

불변의 대상이 중요한 경우는 다양하며 대부분의 경우 보안과 관련이 있습니다. URI는 여기서 좋은 예입니다. (예 : 신뢰할 수없는 코드로 URI가 변경되기를 원하지 않습니다.) 이는 내용이 바뀔 것이라고 걱정하지 않고도 불변의 물체에 대한 참조를 전달할 수 있음을 의미합니다.

도움이 되었기를 바랍니다.

불변의 것들은 결코 변하지 않습니다. 변이 가능한 것들이 변할 수 있습니다. 돌연변이되는 것들이 돌연변이합니다. 불변의 것들이 변하는 것처럼 보이지만 실제로 새로운 변이 가능한 것을 만듭니다.

예를 들어 여기 Clojure의지도가 있습니다

(def imap {1 "1" 2 "2"})
(conj imap [3 "3"])
(println imap)

첫 번째 줄은 새로운 불변의 Clojure지도를 만듭니다. 두 번째 줄은 3과 "3"을지도에 연결합니다. 이것은 이전지도를 수정하는 것처럼 보일 수 있지만 실제로는 새로운 3 "3"가 추가 된 맵. 이것은 불변성의 대표적인 예입니다. 이것이 변한 맵이라면 단순히 3 "3"을 직접 추가했을 것입니다. 에게 같은 오래된지도. 세 번째 줄은지도를 인쇄합니다

{3 "3", 1 "1", 2 "2"}

불변성은 코드를 깨끗하고 안전하게 유지하는 데 도움이됩니다. 이것이 다른 이유와 다른 이유는 기능적 프로그래밍 언어가 불변성과 상태가 낮은 경향이있는 이유입니다.

좋은 질문.

멀티 스레딩. 모든 유형이 불변이라면 인종 조건이 존재하지 않으며 원하는만큼 코드에 많은 스레드를 던지는 것이 안전합니다.

분명히 복잡한 계산을 절약 할 수 없으므로 일반적으로 기능적 비즈니스 소프트웨어를 만들려면 약간의 돌연변이가 필요합니다. 그러나 거래가 어떤 것과 같이 불변성이 어디에 있는지 인식 할 가치가 있습니다.

철학에 대한 자세한 내용은 기능적 프로그래밍과 순도 개념을 찾아보십시오. 컬렉션 또는 정적으로 사용 가능한 객체와 같은 참조를 통해 프로그램을 더욱 순수하고 레이스 조건이 덜 발생하기 쉬운 콜 스택 (메서드에 전달하는 매개 변수)에 더 많이 저장할수록 요즘 더 많은 지역이있는이 주제가 더 중요합니다.

또한 불변성은 프로그램의 가능성을 줄여 버그의 잠재적 복잡성과 잠재력을 줄입니다.

불변의 대상은 당신이 안전하게 변하지 않을 것이라고 가정 할 수있는 것입니다. 그것은 그것을 사용하는 모든 사람이 동일한 가치를보고 있다고 가정 할 수있는 중요한 속성을 가지고 있습니다.

불변성은 일반적으로 대상을 "가치"라고 생각할 수 있으며, 객체의 동일한 사본과 물체 자체 사이에는 효과적인 차이가 없음을 의미합니다.

하나 더 추가하겠습니다. 위에서 언급 한 모든 것 외에도 당신은 또한 불변성을 원합니다.

불변을 불충분하게 만드는 것은 많은 수많은 일반적인 실수를 막을 수 있습니다.

예를 들어, 학생은 학생 # 변경이 없어야합니다. 변수를 설정하는 방법을 제공하지 않으면 (그리고 Const 또는 Final 또는 Language가 지원하는지) 컴파일 시간에이를 시행 할 수 있습니다.

상황이 변하는 것이고 당신이 그들을 통과 할 때 변화를 원하지 않는다면 당신이 통과 할 수있는 defencive 사본을 만들어야합니다. 그런 다음 호출하는 메소드/함수가 원본이 손대지 않은 항목의 사본을 변경하는 경우.

불변의 물건을 만드는 것은 방어력을 사본을 만들기 위해 기억하거나 시간/기억을 취할 필요가 없다는 것을 의미합니다.

실제로 작업하고 각 변수에 대해 생각하면 대다수 (일반적으로 90-95%) 변수가 값이 주어지면 변수가 변경되지 않는다는 것을 알게 될 것입니다. 이렇게하면 프로그램이 쉽게 따라갈 수 있고 버그 수를 줄입니다.

상태에 대한 귀하의 질문에 답하기 위해 상태는 "개체"(클래스 또는 구조물)의 변수가있는 값입니다. 당신이 사람의 "물체"상태를 데려 가면 눈 색깔, 머리 색깔, 머리 길이 등과 같은 것들이 될 것입니다 ... 일부 (눈 색깔)는 변하지 않고 머리 길이와 같은 다른 사람들은 변합니다.

"...내가 왜 그걸 걱정해야 해?"

실제적인 예는 문자열의 반복적인 연결입니다.예를 들어 .NET에서는 다음과 같습니다.

string SlowStringAppend(string [] files)
{
    // Declare an string
    string result="";

    for (int i=0;i<files.length;i++)
    {
        // result is a completely new string equal to itself plus the content of the new
        // file
        result = result + File.ReadAllText(files[i]);
    }

    return result;
}    

string EfficientStringAppend(string [] files)
{
    // Stringbuilder manages a internal data buffer that will only be expanded when absolutely necessary
    StringBuilder result=new SringBuilder();

    for (int i=0;i<files.length;i++)
    {
        // The pre-allocated buffer (result) is appended to with the new string 
        // and only expands when necessary.  It doubles in size each expansion
        // so need for allocations become less common as it grows in size. 
        result.Append(File.ReadAllText(files[i]));
    }

    return result.ToString();
}

불행히도 첫 번째(느린) 함수 접근 방식을 사용하는 것이 여전히 일반적으로 사용됩니다.불변성을 이해하면 StringBuilder를 사용하는 것이 왜 그렇게 중요한지 매우 분명해집니다.

불변의 대상을 변경할 수 없으므로 대체해야합니다 .... "변경하려면". 즉, 교체 한 다음 폐기하십시오. 이 의미에서 "교체"는 한 메모리 위치 (이전 값의)에서 다른 메모리 위치 (새 값)로 포인터를 변경하는 것을 의미합니다.

그렇게 할 때 우리는 이제 추가 메모리를 사용하고 있습니다. 일부는 오래된 가치에 대해, 일부는 새로운 가치에 대해. 또한 일부 사람들은 코드를보고 있기 때문에 혼란스러워합니다.

string mystring = "inital value";
mystring = "new value";
System.Console.WriteLine(mystring); // Outputs "new value";

그리고 스스로 생각하십시오. "하지만 나는 그것을 바꾸고 있습니다. 바로 흑백으로보세요! MyString 출력 '새로운 가치'...... 나는 당신이 그것을 바꿀 수 없다고 생각 했습니까?"

그러나 실제로 후드 아래에서, 무슨 일이 일어나고 있는지, 새로운 기억의 할당, 즉 mystring은 이제 다른 메모리 주소와 공간을 가리키고 있다는 것입니다. 이런 의미에서 "불변"은 MyString의 가치가 아니라 변수 MyString이 그 값을 저장하기 위해 사용하는 메모리를 언급하는 것입니다.

특정 언어에서는 기존 값을 저장하는 메모리를 수동으로 정리해야합니다. 즉, 프로그래머는 명시 적으로 해제해야합니다. 다른 언어로 이것은 .NET의 언어 IE 쓰레기 수집의 자동 기능입니다.

이것이 실제로 날려 버리는 장소 중 하나입니다. 메모리 사용량은 특히 Ashs의 게시물과 같이 문자열과 함께 반복적 인 루프입니다. 반복 루프에 HTML 페이지를 구축하고 있다고 가정 해 봅시다. 여기서 다음 HTML 블록을 마지막으로 끊임없이 추가했으며 차기를 위해 대량 서버 에서이 작업을 수행하고 있다고 가정 해 봅시다. "새 값 메모리"에 대한 이러한 지속적인 할당은 "오래된 값 메모리"가 제대로 정리되지 않으면 빠르게 비싸고 궁극적으로 치명적일 수 있습니다.

또 다른 문제는 일부 사람들이 쓰레기 수집 (GC)과 같은 일이 즉시 발생한다고 가정한다는 것입니다. 그러나 그렇지 않습니다. 더 유휴 기간 동안 쓰레기 수집이 발생하도록 다양한 최적화가 발생합니다. 따라서 메모리가 폐기 된 것으로 표시 될 때와 쓰레기 수집가에 의해 실제로 해방 될 때 사이에는 상당한 지연이있을 수 있습니다.

GC가 메모리가 부족하기 전에 작동 할 기회를 얻지 못하면 자동 쓰레기 수집이없는 다른 언어에서는 반드시 넘어지지 않습니다. 대신 GC는 타이밍이 아무리 나쁘더라도 폐기 된 메모리를 확보하기 위해 가장 높은 우선 순위 프로세스로 시작될 것입니다. 분명히, 이것은 시원하지 않습니다.

따라서 기본적으로 이러한 것들을 염두에두고 코딩 하고이 위험을 피/완화 할 수있는 모범 사례/패턴에 사용하는 언어에 대한 문서를 살펴 봐야합니다.

Ashs 'Post, .NET 및 Strings에서와 같이, 권장되는 관행은 문자열 값을 지속적으로 변경해야 할 필요성에있어 불변의 문자열 클래스보다는 Mutable StringBuilder 클래스를 사용하는 것입니다.

다른 언어/유형에는 유사하게 자체 해결 방법이 있습니다.

왜 불변성?

  1. 그들은 덜 오류가 발생하기 쉬우 며 더 안전합니다.

  2. 불변의 클래스는 변한 클래스보다 설계, 구현 및 사용하기 쉽습니다.

  3. 불변의 객체는 스레드 안전이므로 동기화 문제가 없습니다.

  4. 불변의 객체는 좋은 맵 키와 세트 요소입니다. 일반적으로 일단 생성되면 변경되지 않기 때문입니다.

  5. 불변성으로 인해 코드에 대한 작성, 사용 및 이유가 더 쉬워집니다 (클래스 불변량은 한 번 설정 한 다음 변경되지 않았습니다).

  6. 불변성은 객체간에 충돌이 없기 때문에 프로그램을 더 쉽게 병렬화 할 수 있습니다.

  7. 예외가 있더라도 내부 프로그램 상태는 일관되게됩니다.

  8. 불변의 물체에 대한 참조는 변하지 않을 때 캐시 될 수 있습니다. (즉, 해싱에서 빠른 작업을 제공합니다).

자세한 답변은 내 블로그를 참조하십시오.
http://javaexplorer03.blogspot.in/2015/07/minimize-mutability.html

봐, 나는 당신이 게시 한 링크를 읽지 않았습니다.

그러나 여기에 내 이해가 있습니다.
모든 프로그램은 사용자 입력/외부 변경으로 변경 될 수있는 데이터 (State)에 대한 지식을 보유하고 있습니다.

변수 (변화하는 값)는 상태를 유지하기 위해 유지됩니다. 불변성은 변경되지 않는 일부 데이터를 의미합니다. 당신은 어떤 식 으로든 준비 적이거나 상수와 동일하다고 말할 수 있습니다 (그런 식으로 볼 수 있습니다).

AFAIK, 기능적 프로그래밍에는 불변이 불변이 있습니다 (즉, 값을 보유한 변수에 할당을 사용할 수 없습니다. 할 수있는 것은 원래 값 + 변경을 보유 할 수있는 다른 변수를 만드는 것입니다).

.NET에는 문자열 클래스가 있습니다.
즉, 당신은 그 대신 문자열을 수정할 수 없습니다

문자열 s = "hello"; S.Replace ( "EL", "A")를 쓸 수 있습니다. 그러나 이것은 변수의 내용을 수정하지 않습니다.

내가 할 수있는 것은 s = s.replace ( "el", "a");
이렇게하면 새 변수가 생성되고 값을 s (s의 컨텐츠를 덮어 쓰기)에 할당합니다.

내가 이해할 때 전문가들은 실수를 바로 잡을 수 있습니다.

편집 : 불변 할 수 없음 = 부당 할 수 없으면 가치를 유지하고 대체 할 수 없습니다 (아마도?)

불변의 물체가 제공하는 잠재적 성능 혜택의 예는 WPF API에서 제공됩니다. 많은 WPF 유형의 일반적인 기본 클래스는 다음과 같습니다 Freezable.

몇 가지 WPF 예제는 냉동 물체 (런타임에 불변이 불충분 함)가 잠금 및 복사가 필요하지 않기 때문에 응용 프로그램 성능을 크게 향상시킬 수 있음을 시사합니다.

개인적으로 나는 불변성의 개념이 내가 가장 자주 사용하는 언어로 표현하기가 더 쉽기를 바랍니다. c#. 이있다 readonly 필드에 사용할 수있는 수정 자. 보고 싶어요 readonly 유형에 대한 수정 자도 유형의 유형 인 유형에만 허용되는 유형에만 허용됩니다. 본질적으로 이것은 모든 상태가 시공 시간에 주입되어야한다는 것을 의미하며, 전체 객체 그래프가 얼어 붙을 것임을 의미합니다. 나는 이것이 CLR에 고유 한이 메타 데이터라고 생각한다. 그러면 GC의 쓰레기 분석을 최적화하는 데 쉽게 사용할 수 있습니다.

죄송합니다. 불변성이 인종 조건을 예방하는 이유 (이 예에서는 읽기 위험 후에 쓰기)?

shared v = Integer(3)
v = Integer(v.value() + 1) # in parallel

불변성은 가치에 관한 것이며 가치는 사실에 관한 것입니다. 무언가를 변경할 수 있으면 특정 값을 연결할 수 없기 때문에 변경할 수없는 경우 가치가 있습니다. 객체는 상태 A로 초기화되었고 프로그램 실행 중 상태 B 및 상태 C로 돌연변이되었다는 것은 객체가 단일 특정 값을 나타내지 않고 컨테이너, 메모리의 장소에서의 추상화, 더 이상 아무것도 없음을 의미합니다. 당신은 그러한 컨테이너를 신뢰할 수 없으며,이 컨테이너는 당신이 가진 가치가 있다고 믿을 수 없습니다.

예시로 가자 - 코드에서 책 클래스의 인스턴스가 생성된다고 상상해 봅시다.

Book bookPotter =  new Book();
bookPotter.setAuthor('J.K Rowling');
bookPotter.setTitle('Harry Potter');

이 인스턴스에는 저자 및 제목과 같은 일부 필드가 있습니다. 모든 것이 정상이지만 코드의 일부에서는 다시 세터가 사용됩니다.

Book bookLor =  bookPotter; // only reference pass
bookLor.setAuthor('J.R.R Tolkien');
bookLor.setTitle('Lords of The Rings');

다른 변수 이름으로 속지 마십시오. 실제로 동일한 인스턴스입니다. 코드는 동일한 인스턴스에서 세터를 다시 사용하고 있습니다. 그것은 Bookpotter가 실제로 Harry Potter Book이 아니라는 것을 의미합니다. Bookpotter는 알려지지 않은 책이있는 곳으로 만 포인터입니다. 즉, 책보다 선반 인 것 같습니다. 그러한 대상에 대해 어떤 신뢰를 할 수 있습니까? 해리포터 북,로서 책이거나 둘 다?

클래스의 변이 가능한 인스턴스는 클래스 특성을 가진 알 수없는 상태에 대한 포인터 일뿐입니다.

그렇다면 어떻게 돌연변이를 피하십시오? 규칙이 매우 쉽습니다.

  • 생성자 또는 빌더를 통해 원하는 상태로 객체를 구성하십시오
  • 캡슐화 된 객체 상태에 대한 세터를 생성하지 마십시오
  • 그 방법 중에서 캡슐화 된 객체 상태를 변경하지 마십시오.

이 몇 가지 규칙은보다 예측 가능하고 신뢰할 수있는 객체를 가질 수 있습니다. 우리 예제로 돌아가서 위의 규칙에 따라 예약하십시오.

Book bookPotter =  new Book('J.K Rowling', 'Harry Potter');
Book bookLor = new Book('J.R.R Tolkien', 'Lord of The Rings');

모든 것이 구성 단계,이 경우 생성자 중에 설정되지만 더 큰 구조의 경우 건축업자가 될 수 있습니다. 객체에는 세트가 존재하지 않으며 책은 다른 책으로 돌연변이 할 수 없습니다. 이 경우 Bookpotter는 Harry Potter Book의 가치를 나타내며 이것이 변하지 않는 사실임을 확신 할 수 있습니다.

더 넓은 불변성 범위에 관심이 있다면,이 중간 기사에서 JavaScript와 관련하여 주제에 관한 것입니다. https://medium.com/@macsikora/the-state-of-immutability-169D2CD11310.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top