Closed epicblues closed 2 years ago
민성님이 질문해주신걸 생각해보다가 추가로 궁금한 점이 생겼습니다.
따라서 래퍼의 불변식을 쉽게 파괴할 수 있지만 ..
래퍼클래스는 불변 클래스라고 알고있는데, 책에서 말하는 위 문장을 이해하지 못했습니다;;
☠️ 제가 질문을 제대로 이해한지는 모르겠지만 제가 생각한것을 적어보겠슴니다
이부분에 대한 저의 해석은, 래퍼클래스로부터 값을 받아옴으로써 래퍼클래스 안에 있는 값들에 접근을 할 수 있겠지만,
래퍼클래스가 값을 전달해주는 방식은 새로 만들거나 값을 가져오는 것이다. (민환님이 소개해주신 일급컬렉션 소개 中)
이 글에서 래퍼클래스의 반환형은 방어적 복사본이라고 생각했고 이번장의 주제인 '방어적 복사본을 만들라' 와 일치해서 다음과 같은 문장이 작성되었다고 생각합니다!
// 1. B가 **가지고있는 A의 참조를 그대로** 클라이언트 에게 준다.
class B {
A a;
public A getA() {return a;}
}
//2. B가 **새로운 A인스턴스의 참조** 를 전달한다 (방어적복사)
class B {
A a;
public A getA() {return new A(a);}
}
이러한 상황에서 B가 싱글톤으로 관리되며, 이를 여러 클라이언트에서 공유하여 사용하는 상황이라고 가정해보면
// 악의적인(혹은 미숙한) 클라이언트가 A클래스를 받아와서 의도하지 않은 행동을 수행하고 있다
var a = b.getA(); // 원본 A를 받았다
a.setIllegalValue(illegal); // 원본A값이 수정되었다
// 다음번 사용자가 다시 A를 사용하려고 하고 있다.
var a = b.getA(); // 원본 A를 받았다
var value = a.getValue(); // 앞에서 수정된 이상한 A의 값을 받았다
doSomething(value); // ⚠️오류!
이렇게 사용하는 쪽에서 이상한 짓을 해버리면 B에 있는 원본 A값 자체가 바뀐것이기 때문에 다음에 사용하는 클라이언트 2는 B에서 A와 연결된 모든 동작이 전체적으로 이상한 동작하게 될것입니다. 꼭 A클래스를 사용하지 않더라도요
그렇지만 이 상황에서 A를 2번 방법과 같이 방어적 복사를 해서 넘겨준다면 다른 클라이언트가 B클래스를 사용하더라도 A로 인한 사이드이펙트가 존재하지 않을겁니다!
// 악의적인(혹은 미숙한) 클라이언트
var a = b.getA(); // A의 복사본이 반환되었다.
a.setIllegalValue(illegal); // 복사본에 이상한 값을 셋팅했다.
var value = a.getValue(); // 본인이 셋팅한 이상한 값을 본인이 받았다.
doSomething(value); // 본인이 피해를 입었다 쿨럭
// 다음번 사용자 var a = b.getA(); // A의 복사본이 반환되었다 var value = a.getValue(); // B에 있는 원본은 변화되지 않았으므로 정상적인 값을 받음 doSomething(value); // 정상수행
따라서 이런 참조를 가지고 있는 클래스를 만들때에는
이 참조를 클라이언트에게 넘겨줄때 (어떤 사이드 이펙트가 일어날지 모르니)
방어적으로 복사해서 넘겨주라는 이야기로 이해했습니다.