반응형

규칙 13에서 객체 필드 변수는 절대로 public으로 선언하지 말고 getter와 같은 접근자 메서드를 사용하라고 설명했다.

규칙 14에서는 위 내용에 대해 간단하게 설명한다.

 

객체 필드 변수를 public으로 선언하게 되면 외부에서 데이터를 쉽게 조작할 수 있어 캡슐화의 이점을 누릴 수 없다.

 

예를 들어 양수만 표현하는 Point 클래스를 아래와 같이 선언한다면 생성자에서는 음수를 넣을 수 없지만 정상적으로 객체 생성 후 클라이언트가 음수를 직접 세팅할 수 있다.

public class PositivePointWithPublicField {
	public double x;
	public double y;

	public PositivePointWithPublicField(double x, double y) {
		if (x < 0 || y < 0) {
			throw new IllegalArgumentException();
		}

		this.x = x;
		this.y = y;
	}
}

public class Client {
	public static void main(String[] args) {
		PositivePointWithPublicField point = new PositivePointWithPublicField(0, 0);
		point.x = -5;
		point.y = -10;

	}
}

 

하지만 필드를 private로 선언하고 getter를 사용하게 되면 위를 방지할 수 있다.

public class PositivePointWithPrivateField {
	private double x;
	private double y;

	public PositivePointWithPrivateField(double x, double y) {
		if (x < 0 || y < 0) {
			throw new IllegalArgumentException();
		}

		this.x = x;
		this.y = y;
	}

	public double getX() {
		return x;
	}

	public double getY() {
		return y;
	}
}


public class Client {
	public static void main(String[] args) {
		PositivePointWithPrivateField point = new PositivePointWithPrivateField(0, 0);

		// 컴파일 에러
		point.x = -5;
		point.y = -10;

	}
}

 

getter 메서드(또한 setter)는 너무나 많이 사용하기 때문에 IDE에서 자동으로 생성해주는 기능이다. 뿐만 아니라 lombok과 같은 라이브러리에서는 어노테이션을 사용하여 자동으로 생성할 수 있다.

@Getter
public class PositivePointWithPrivateField {
	private double x;
	private double y;

	public PositivePointWithPrivateField(double x, double y) {
		if (x < 0 || y < 0) {
			throw new IllegalArgumentException();
		}

		this.x = x;
		this.y = y;
	}

}

 

다만 Immutable 필드(final 선언)라면 초기에 한 번만 설정할 수 있으므로 public으로 선언하여도 아래와 같이 클라이언트가 조작하지 못하므로 public으로 선언해도 된다. 하지만 굳이 이럴 바에는 getter를 사용하는 게 더 맞다. 또한 public 필드를 두게 되면 후에 호환성을 위해 항상 해당 필드를 유지해야 한다. 하지만 getter를 제공한다면 이미 작성된 클라이언트 코드는 깨트리지 않을 수 있다.

public class PositivePoinWithFinalField {
	public final double x;
	public final double y;

	public PositivePoinWithFinalField(double x, double y) {
		if (x < 0 || y < 0) {
			throw new IllegalArgumentException();
		}

		this.x = x;
		this.y = y;
	}
}

public class Client {
	public static void main(String[] args) {
		PositivePoinWithFinalField point = new PositivePoinWithFinalField(0, 0);

		// final이서 컴파일 에러
		point.x = -5;
		point.y = -10;

	}
}

 

참고

자바에서 제공하는 클래스 중에 규칙 14를 깨트린 클래스들이 존재한다. 따라서 이런 클래스는 코딩할 때 참고하지 않는 것이 좋다.

 

// java.awk.Point
public class Point extends Point2D implements java.io.Serializable {
    public int x;
    public int y;
     
    // ...
}

// java.awk.Dimension
public class Dimension extends Dimension2D implements java.io.Serializable {
    public int width;
    public int height;
    
    // ...
}
반응형

+ Recent posts