-
이펙티브 자바 Item 16 - public 클래스에서는 public필드가 아닌 접근자 메서드를 사용하라언어/Effective Java 2024. 5. 30. 09:52
1. 접근자 메서드를 활용한 데이터 캡슐화
- 대표적인 클래스 작성 실수: 인스턴스 필드만을 모아놓은 퇴보한 클래스
- 인스턴스 필드만을 모아놓은 클래스는 데이터 직접 접근할 수 있으나 캡슐화의 이점을 제공하지 못한다.
public class Point { public double x; public double y; }
- 캡슐화가 전혀 안되기 때문에 아래와 같은 단점을 수반한다.
- API를 수정하지 않고는 내부 표현을 바꿀 수 없다.
- 불변식을 보장하지 못한다.
- 외부에서 필드에 접근할 때 부수작업을 수행할 수 없다.
*API 수정부분
Point.getValue() 같은 메서드를 호출해서 x,y를 얻는다고 했을 때 내부 구현 로직이 캡슐화되어 있기 때문에 얼마든지 바꿀 수 있음
Point.x로 접근했을 때, 만약 x의 이름이 xy로 바뀐다면, Point.x를 사용하는 모든 클래스를 수정해줘야할 것임
2. 클래스 캡슐화
class Point { private double x; private double y; public Point(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } public void setX(double x) { this.x = x; } public void setY(double y) { this.y = y; } }
- getter/setter 메서드를 통해 언제든지 내부 표현을 바꿀 수 있다.
- 불변식이 보장된다.
- 클라이언트는 메서드를 통해서만 필드에 접근 가능하다.
- 외부에서 필드에 접근할 때 부수 작업을 수행 시킬 수 있다.
- getter/setter 메서드에 얼마든지 추가 가능하다.
객체지향의 장점을 이끌어내려면, 아무리 단순한 데이터(필드)라도 이처럼 캡슐화를 진행하는 것이 좋다.
2.1 private 중첩 클래스
- 하지만 pakage-private 혹은 private 중첩 클래스라면 데이터 필드를 노출한다 해도 문제가 없다
public class TopPoint { private static class Point { public double x; public double y; } public Point getPoint() { Point point = new Point(); // TopPoint 외부에선 point.x = 3.5; // Point 클래스 내부 조작이 point.y = 4.5; // 불가능 하다. return point; } }
- 위와 같이 private 클래스를 중첩시키면 TopPoint 클래스에서는 얼마든지 Point클래스의 필드를 조작할 수 있지마느 외부 클래스에서는 Point 클래스의 필드에 직접 접근 할 수 없다.
- package-private 클래스 역시 해당 클래스가 포함되는 패키지 내에서만 조작이 가능하고 패키지 외부에서는 접근이 불가능 하므로, 처음 제시된 3가지 문제점을 모두 메꿀 수 있다.
- point.x로 접근해서 사용하면 훨씬 사용이 편리하긴 하다. 이런 장점을 살리면서 캡슐화의 이점도 가져간다.
*public class에서 public 필드를 만들면 공개 API라서 클라이언트가 전 세계이다. 이는 수정이 매우 어렵다.
하지만, package-private나 private 중첩 클래스에 public은 수정 범위가 패키지 내부나 클래스 내부이므로, 비교적 수정이 용이하다.
public을 노출하되, 불편 필드로 만들기
public class Time { private static final int HOURS_PER_DAY = 24; private static final int MINUTES_PER_HOUR = 60; public final int hour; public final int minute; public Time(final int hour, final int minute) { this.hour = hour; this.minute = minute; } }
- public 클래스 필드가 불변이라면 직접 노출할 때의 단점이 조금 줄어든다.
- 다만 API를 변경하지 않고는 표현 방식을 바꿀 수 없고, 필드를 읽을 때 부수적인 작업을 수행할 수 없다는 단점이 변하지 않는다.
'언어 > Effective Java' 카테고리의 다른 글
이펙티브 자바 Item 18 - 상속보다는 컴포지션을 사용하라 (1) 2024.05.31 이펙티브 자바 Item 17 - 변경 가능성을 최소화하라 (0) 2024.05.30 이펙티브 자바 Item15 - 클래스와 멤버의 접근 권한을 최소화하라 (0) 2024.05.29 이펙티브 자바 Item 14 - Comparable을 구현할지 고려하라 (0) 2024.05.29 이펙티브 자바 Item 13 - clone 재정의는 주의해서 진행하라 (0) 2024.05.29