접근하는 방법도 있어서는 안된다. 아래는 Java에서 가변 객체의 예를 나타낸다. class Cart < T > { private final List < T > items ; public Cart ( List < T > items ) { this. items = items ; } public List < T > getItems { return items ; } public int total { / * return sum of the prices * / } } 이 클래스의 인스턴스는 불변적이지 않다. 왜냐하면 인스턴스화 할때 전달한 List 객체를 어딘가에서 보유하는 것으로 필드가 변경될 가능성이 있으며 getItems를 호출해 가변적인 items 필드에 접근할 수 있기 때문이다. 아래 ImmutableCard 클래스는 부분적으로 불변하도록 작성한 예이다. class ImmutableCart < T > { private final List < T > items ; public ImmutableCart ( List < T > items ) { this. items = Arrays. asList ( items. toArray ) ; } public List < T > getItems { return Collections. unmodifiableList
items ; public : Cart ( std : : vector < T > v ) : items ( v ) { } std : : vector < T > & getItems { return items ; } const std : : vector < T > & getItems const { return items ; } int total const { / * return sum of the prices * / } } ; 위 C의 예는 불변, 가변 겸용으로 만든 것이다. 이를 위해 두 개의 생성자 ( Constructor ) 를 준비할 필요는 없으며, 실제로 가능하지도 않다. Cart 타입의 변수를 선언할 때 const 선언 여부로 결정된다. 이전에 작성한 Java 코드가 불변할 수 없는 이유는 또 있는데 클래스를 상속할 수 있다는 것에서 기인한다. 서브 클래스에서 멋대로 items를 변경하는 setter 메서드가 구현될 수 있다. 따라서 class에 final 수식자를 부여한다. 혹시 모르니 메서드 인수에도 final 수식자를 부여한다. 이어서 " 방어적 복사 " 라는 기법을 이용해 getItems에서 반환 받은 List가 변경되더라도 ImmutableCard 클래스가 보유하는 items 필드의 내용이 변경
링크 편집 이 문서는 2019년 5월 6일 ( 월 ) 01 : 13에 마지막으로 편집되었습니다. 모든 문서는 크리에이티브 커먼즈 저작자표시 - 동일조건변경허락 3. 0에 따라 사용할 수 있으며, 추가적인 조건이 적용될 수 있습니다. 자세한 내용은 이용 약관을 참고하십시오. 미국 및 다른 국가에 등록되어 있는 Wikimedia Foundation, Inc. 소유의 등록 상표입니다. 개인정보 정책 위키백과 소개 면책 조항 개발자 쿠키 정책 모바일 보기
/ * return sum of the prices * / } } 인수의 객체를 일단 clone으로 복사하고 나서 필드에 대입함으로써 인수에 전달되기 전의 List 객체와 참조를 떼어 낼 수 있다. 따라서 인수에 전달되기 전의 List 객체를 변경해도 ImmutableCard에 있는 List 객체 items 까지 영향이 미치지 않는다. 방어적 복사는 getItems 메서드에서도 할 필요가 있다. 추가적으로 코드를 설명하자면 Collections. checkedList ( List < T >, Class < T > ) 는 items가 다른 메서드에 전달 됐을 때 리스트에 T와 다른 타입이 대입 되는 것을 막기 위해 사용한다. Collections. unmodifiableList ( List < T > ) 는 리스트의 요소를 변경하지 못하도록 final 하기 위해 사용한다. 또, 클래스가 불변인지 확인하는 하나의 방법으로 FindBugs라는 도구를 사용할 수 있다. 이는 버그의 원인이 되는 코드를 자동으로 검출해주는 도구인데 불변 클래스를 작성할 때에도 도움을 준다. 만약 자바스크립트에서 불변 객체를 운영하고 싶다면 페이스북의 이용한다. 참고자료 [ 편집 ] Perl Design Pa
; } public List < T > getItems { return Collections. unmodifiableList ( items ) ; } public int total { / * return sum of the prices * / } } 아래는 Ruby에서의 비슷한 예다. class Cart def initialize ( items ) = items. dup. freeze end def items. clone end def total # sum of the prices end end 이제는 items를 변경할 수 없다. 하지만, 리스트 items의 요소도 불변이라는 보증은 없다. 해법 중 하나로는 Decorator 패턴으로 리스트의 각 요소를 랩핑할 수 있다. C 에서는 Cart를 const - correct한 구현을 하는 것으로 인스턴스를 불변 ( const ) 또는 가변 즉, 원하는대로 생성하도록 할 수 있다. 쉽게 말해 2개의 다른 getItems를 제공한다. template < typename T > class Cart { private : std : : vector < T > items ; public : Cart ( std : : vector < T > v ) : items ( v ) { }
##에서 반환 받은 List가 변경되더라도 ImmutableCard 클래스가 보유하는 items 필드의 내용이 변경되지 않도록 복사한다. 위에서는 List를 배열로 변환하고 되돌리는 방법이 사용됐지만 여기에서는 Object. clone ( Object ) 메서드를 이용해 해결한다. final class ImmutableCart < T > { private final List < T > items ; public ImmutableCart ( final List < T > items ) { / / 방어적 복사한 뒤 리스트 요소의 실행 시 타입 검사를 한다. / / 리스트의 요소를 final로 한다. this. items = Collections. unmodifiableList ( Collections. checkedList ( ( List < T > ) ( ( List < T > ) ( List < T > ) items. clone, T. class ) ) ; } public List < T > getItems { / / 내부 필드의 방어적 복사 return ( List < T > ) items. clone ; } public int total { / * return sum of the prices * / } } 인수의 객체를 일단 clone으로 복사하고 나서 필드에 대입
##해도 외부에서 그 객체의 상태가 변하지 않은 것 처럼 보인다면 불변 객체로 보기도 한다. 예를 들어, 비용이 큰 계산의 결과를 캐시하기 위해 메모이제이션 ( Memoization ) 을 이용하더라도 그 객체는 여전히 불변하다고 볼 수있다. 불변 객체의 초기 상태는 대개 생성 시에 결정되지만 객체가 실제로 사용되는 순간까지 늦추기도 한다. 불변 객체를 사용하면 복제나 비교를 위한 조작을 단순화 할 수 있고, 성능 개선에도 도움을 준다. 하지만 객체가 변경 가능한 데이터를 많이 가지고 있는 경우엔 불변이 오히려 부적절한 경우가 있다. 이 때문에 많은 프로그래밍 언어에서는 불변이나 가변 중 하나를 선택할 수 있도록 하고 있다. 목차 1 배경 2 구현 3 참고자료 4 외부 링크 배경 [ 편집 ] 대부분의 객체 지향 언어에서 객체는 참조 ( reference ) 형태로 전달하고 받는다. Java, C, Python, Ruby 등이 그 예이다. 객체가 참조를 통해 공유돼 있다면 그 상태가 언제든지 변경될 가능성도 커지므로 문제가 된다. 불변 객체는 객체를 복제할 때 객체 전체가 아니라 단순히 참조만 복사하고 끝난다. 참조는 보통 객체 그 자체보다 훨씬 작아서 ( 전형적으로 포인터 크기 ), 메모리가 절감되며 프로그램의
하다고 생각하면 된다. 객체 전체 대신 참조를 복제하는 기법은 인턴 ( intern, 문자열 객체를 만들면 매번 메모리에 새로운 객체가 만들어지는데 이를 인턴하여 문자열 풀 - String Pool - 에 저장하고 그 뒤 같은 문자열이 호출되면 풀에서 참조를 복사해 반환하는 기법 ) 으로 알려져 있다. 인턴이 사용되고 있다면 2개의 객체가 같다고 판단되는 경우는 참조가 같은 경우다. 구현 [ 편집 ] 불변이란, 객체가 컴퓨터의 메모리 내에서 쓰기를 할 수 없다는 뜻이 아니다. 오히려 불변은 컴파일 시의 문제이며, 프로그래머가 「 무엇을 해야하는가 」 이지 반드시 「 무엇이 가능한가 」 가 아니다. 현대적인 하드웨어가 지원하고 있는 가변과 불변의 장점이 잘 섞인 기법은 카피 온 라이트 ( Copy - On - Write ) 다. 이 기법에서는 이용자가 시스템에 객체를 복제하도록 명하면 복사 대신 동일한 객체를 가리키는 참조를 만든다. 그리고 이용자가 그 참조를 통해 객체를 변경하면 그때 진짜 복제를 만들고 그것을 가리키는 참조를 다시 생성한다. 이에 의해 다른 이용자는 영향을 받지 않는다. 왜냐하면 여전히 원본 객체를 참조하고 있기 때문이다. 카피 온 라이트 환경에서 모든 이용자는 가변 객체를 갖고 있는 것처럼 보이지만 그
불변객체 - 위키백과, 우리 모두의 백과사전 불변객체 위키백과, 우리 모두의 백과사전. 둘러보기로 가기 검색하러 가기 이 문서는 영어 위키백과의 Immutable - object 문서를 번역하여 문서의 내용을 확장할 필요가 있습니다. 신뢰성 있고 확인할 수 있는 출처가 제시되도록 번역하여 주십시오. 번역을 완료한 후에는 { { 번역된 문서 } } 틀을 토론창에 표기하여 저작자를 표시하여 주십시오. 문맥상 이해를 돕기 위해 관련 문서를 같이 번역해주시는 것이 좋습니다. 번역을 확장할 필요가 있는 다른 문서를 보고 싶으시다면 분류 : 번역 확장 필요 문서를 참고해주세요. 객체 지향 프로그래밍에 있어서 불변객체 ( immutable object ) 는 생성 후 그 상태를 바꿀 수 없는 객체를 말한다. 반대 개념으로는 가변 ( mutable ) 객체로 생성 후에도 상태를 변경할 수 있다. 객체 전체가 불변인 것도 있고, C에서 const 데이터 멤버를 사용하는 경우와 같이 일부 속성만 불변인 것도 있다. 또, 경우에 따라서는 내부에서 사용하는 속성이 변화해도 외부에서 그 객체의 상태가 변하지 않은 것 처럼 보인다면 불변 객체로 보기도 한다. 예를 들어, 비용
끝난다. 참조는 보통 객체 그 자체보다 훨씬 작아서 ( 전형적으로 포인터 크기 ), 메모리가 절감되며 프로그램의 성능에도 좋다. 가변 객체는 참조 복사 기법으로 다루기 곤란하다. 이유는 가변 객체의 참조를 가지고 있는 어떤 장소에서 객체를 변경하면 참조를 공유하는 모든 장소에서 그 영향을 받기 때문이다. 이것이 의도한 동작이 아니라면 참조를 가지고 있는 다른 장소에 변경 사실을 통지하고 대처하는 추가 대응이 필요하다. 이런 경우 비용은 조금 들지만 참조가 아닌 객체 전체를 방어적 복사 ( defensive copy ) 하는 간단한 방법으로 대응할 수 있다. 또는, Observer 패턴을 가변 객체의 변경에 대처하는 방법으로 사용할 수 있다. 불변 객체는 멀티 스레드 프로그래밍에서도 유용하다. 데이터가 불변 객체에 저장돼 있다면 복수의 스레드에 의해서 특정한 스레드의 데이터가 변경될 우려없이 데이터에 접근할 수 있다. 즉, 배타 제어 ( mutual exclusion ) 를 할 필요가 없다. 쉽게 말해 불변 객체가 가변 객체보다 스레드 세이프 ( Thread - safe ) 하다고 생각하면 된다. 객체 전체 대신 참조를 복제하는 기법은 인턴 ( intern, 문자열 객체를 만들면 매번 메모리에
객체 지향 프로그래밍에 있어서 불변객체(immutable object)는 생성 후 그 상태를 바꿀 수 없는 객체를 말한다. 반대 개념으로는 가변(mutable) 객체로 생성 후에도 상태를 변경할 수 있다. 객체 전체가 불변인 것도 있고, C에서 const 데이터 멤버를 사용하는 경우와 같이 일부 속성만 불변인 것도 있다. 또, 경우에 따라서는 내부에서 사용하는 속성이 변화해도 외부에서 그 객체의 상태가 변하지 않은 것처럼 보인다면 불변 객체로 보기도 한다. 예를 들어, 비용이 큰 계산의 결과를 캐시하기 위해 메모이제이션(Memoization)을 이용하더라도 그 객체는 여전히 불변하다고 볼 수있다. 불변 객체의 초기 상태는 대개 생성 시에 결정되지만 객체가 실제로 사용되는 순간까지 늦추기도 한다. 불변 객체를 사용하면 복제나 비교를 위한 조작을 단순화 할 수 있고, 성능 개선에도 도움을 준다. 하지만 객체가 변경 가능한 데이터를 많이 가지고 있는 경우엔 불변이 오히려 부적절한 경우가 있다. 이 때문에 많은 프로그래밍 언어에서는 불변이나 가변 중 하나를 선택할 수 있도록 하고 있다.