2026-01-13
1일 1아티클
LY
불변 클래스의 상속
문제 상황
-
상속이 불변성을 깨뜨린다 ```java // 부모 클래스: 불변 리스트 // 상속이 가능하도록 열려 있음 (Java에서는 기본적으로 상속 가능) public class ImmutableIntList { // 자식 클래스에서 접근할 수 있도록 protected로 선언 protected final int[] valueArray;
public ImmutableIntList(int… values) { this.valueArray = values; }
public int get(int index) { return valueArray[index]; } }
// 자식 클래스: 부모는 ‘불변’이라지만, 자식은 ‘가변’으로 만들어버림 public class MutableIntList extends ImmutableIntList { public MutableIntList(int… values) { super(values); }
// 부모의 배열에 접근해서 값을 바꿔버리는 메서드 추가
public void set(int index, int value) {
this.valueArray[index] = value;
} }
MutableIntList mutable = new MutableIntList(1, 2, 3); ImmutableIntList immutable = mutable; // 다형성: 부모 타입으로 참조
// ‘불변’ 리스트라고 믿고 있는데, 값이 바뀜! 😱 mutable.set(0, 999); System.out.println(immutable.get(0)); // 999 출력
2. 메서드 오버라이딩
```java
public class SneakyIntList extends ImmutableIntList {
private int cheatValue = 0;
// get 메서드를 조작해서 매번 다른 값을 주게 만듦
@Override
public int get(int index) {
if (cheatValue > 0) return cheatValue;
return super.get(index);
}
public void changeCheatValue(int value) {
this.cheatValue = value;
}
}
해결 방법
- 확실한 불변성 보장을 하려면, 클래스를 상속하지 못하게 막을 것
- Java의 경우, 클래스의 final 선언 및 필드의 private final 선언
// 상속 불가능하게 final 클래스로 선언 public final class SafeImmutableIntList { private final int[] valueArray; public SafeImmutableIntList(int... values) { // 배열의 참조가 아닌 복사본을 저장해야 안전함 (방어적 복사) this.valueArray = values.clone(); } public int get(int index) { return valueArray[index]; } // set 메서드 없음 }
- Java의 경우, 클래스의 final 선언 및 필드의 private final 선언
- 가변 객체는 불변 객체 상속 X
- 불변 객체도 가변 객체 상속 X (부모의 set 메서드가 자식에게 노출되어 런타임 에러 유발)
- 필요하다면, 읽기 전용의 공통 부모를 두고 각각 상속받을 것!
오늘 배운 것
- 아이디어 2차 컨펌 (기능 구체화)
내일 할 일
- 아이디어 3차 컨펌 (교보재 신청)