책에서는 다섯 가지 규칙을 따르면 된다고 말한다.
public final
도 사용 가능하지만 해당 클래스 내에서도 변경할 수 없으므로 권하지는 않음(item-15,item-16)참조라는 것은 해당 값을 바꿀 수가 있쥬?
/**
* 불변(final) 복소수 클래스
*/
public final class Complex {
private final double re;
private final double im;
/**
* public 생성자
* @param re
* @param im
*/
public Complex(double re, double im) {
this.re = re;
this.im = im;
}
/**
* 더하기 메서드
* @param c
* @return
*/
public Complex plus(Complex c) {
/**
* 객체의 값을 수정하지 않고 새로운 Complex 인스턴스를 만들어(new) 반환(return)
* 원하는 값을 반환하지만, 피연산자 자체는 그대로인 프로그래밍 패턴 -> 함수형 프로그래밍
* 객체의 값이 변경되지 X
* 이런 방식으로 프로그래밍을 하면 불변이 되는 영역의 비율이 높아지는 장점을 누릴 수 있다
*/
return new Complex(re + c.re, im + c.im);
}
}
불변객체는 생성된 시점의 상태를 파괴될 때까지 그대로 간직하는데 이로 인해 얻을 수 있는 이점은 다음과 같다.
public static final
로 제공 (코틀린에서는 const val
)모든것이 좋아보이는 불변객체.. 단점도 있쥬..
BigInteger moby = ...; //불변 객체
moby = moby.flipBit(0);
BigSet moby = ...; //가변 객체
moby.flip(0); //=이 없는 것 보이시쥬?
String
의 StringBuilder
위에서는 불변클래스 설계시 final 클래스를 사용하라고 하였지만 조금 더 유연한 방법이 한가지 남았다.🌝
/**
* 복소수 클래스
*/
public class Complex { //final 없는거 보이시쥬?
private final double re;
private final double im;
/**
* private 생성자 -> 외부에서 해당 생성자 접근 X
* @param re
* @param im
*/
private Complex(double re, double im) {
this.re = re;
this.im = im;
}
// public 정적 팩터리
public static Complex valueOf(double re, double im) {
//이런식으로 할땐 final이 아닌 클래스임에도 접근할 수 있는 내부 값이 없기 때문에(private) 사실상 final이 된다.
return new Complex(re, im);
}
}
어떤 메서드도 객체의 상태 중 외부에 비치는 값을 변경할 수 없다.
로 완화 가능 kotlin-in-action 책에서는
코틀린의 기본 가시성이 final이라고 했는데 자바의 이런 특성으로 코틀린에서는 이를 변경했겠구나 라는 생각이 들었다.