[아이템16] public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라

2024. 10. 5. 20:27·1️⃣ 백앤드/이펙티브 자바

1. 접근자 사용

public class Point {
    public double x;
    public double y;
}

 

위 Point 클래스처럼 public 클래스에서 필드 접근 제한을 public 으로 선언한다면, 캡슐화의 이점을 제공할 수 없다. 내부 구현을 수정하기 위해서 API 를 전면 수정해야하며, 외부로 노출되어 있어 불변을 보장할 수 없고, 외부에서 필드에 접근 시 다른 로직을 끼워넣을 수도 없다. 객체 지향 설계를 위해, 이러한 필드들을 모두 private 으로 바꾸고 public 접근자를 추가하자.

public class Point {
    public double x;
    public double y;

    public Point(final double x, final double y) {
        this.x = x;
        this.y = y;
    }

    public double getX() {
        return x;
    }

    public void setX(final double x) {
        this.x = x;
    }

    public double getY() {
        return y;
    }

    public void setY(final double y) {
        this.y = y;
    }
}

 

접근자를 제공함으로써 클래스 내부 로직을 언제든 끼워넣을 수 있는 유연성을 제공할 수 있다.

 

2. package-private 클래스 / private 중첩 클래스

package-private 패키지 전용 클래스는 해당 패키지 안에서만 접근 가능하다. 이 경우 필드를 노출해도 외부 패키지에서는 접근할 수 없으므로 문제가 없다.

// Package-private class
class Person {
    public String name; // 필드를 공개적으로 노출

    public Person(String name) {
        this.name = name;
    }

    String getName() {
        return this.name;
    }
}

 

private 중첩 클래스는 그를 둘러싼 외부 클래스에서만 접근 가능하다. 따라서 중첩 클래스의 필드를 노출해도 외부에서는 접근할 방법이 없으므로 안전하다고 할 수 있다.

public class OuterClass {
    // Private Nested Class
    private class InnerClass {
        public String data = "Nested Class Data"; // 필드 공개적으로 노출

        String getData() {
            return data;
        }
    }

    public void showData() {
        InnerClass inner = new InnerClass();
        System.out.println(inner.data);  // 외부 클래스에서 접근 가능
    }
}

 

이 방식은 접근자 방식보다 훨씬 깔끔하고, 패키지 바깥 코드는 전혀 손대지 않고 구현 동작을 수정할 수 있다.

3. public 클래스의 필드를 노출한 사례

대표적인 예로, java.awt.package 패키지의 Point 와 Dimension 클래스가 있다. 

public 클래스에서 public 필드로 외부에 노출

 

4. 불변만은 보장하자

비록, public 클래스의 필드가 public 이라 할지라도 불변이라면 직접 노출할 때의 단점은 조금 줄어들 것이지만, 좋은 생각은 아니다. 위에서 문제로 제기했던 내부 구현을 수정하기 위해서 API 를 전면 수정해야하며 외부에서 필드에 접근 시 다른 로직을 끼워넣을 수도 없다. 라는 문제는 그대로 노출되지만, 불변만을 보장할 뿐이다. 예를 들어, 아래 Time 클래스는 각 인스턴스가 유효한 시간을 표현함을 보장한다.

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;
    }   
}
...

'1️⃣ 백앤드 > 이펙티브 자바' 카테고리의 다른 글

[아이템18] 상속보다는 컴포지션을 사용해라  (0) 2024.10.09
[아이템17] 변경 가능성을 최소화하라  (1) 2024.10.06
[아이템15] 클래스와 멤버의 접근 권한을 최소화하라  (0) 2024.10.04
[아이템14] Comparable 을 구현할지 고려하라  (1) 2024.09.25
[아이템13] clone 재정의는 주의해서 진행하라  (0) 2024.09.25
'1️⃣ 백앤드/이펙티브 자바' 카테고리의 다른 글
  • [아이템18] 상속보다는 컴포지션을 사용해라
  • [아이템17] 변경 가능성을 최소화하라
  • [아이템15] 클래스와 멤버의 접근 권한을 최소화하라
  • [아이템14] Comparable 을 구현할지 고려하라
HOZINU
HOZINU
주니어 백앤드 개발자의 세상만사 이모저모. 주로 개발 이야기를 다룸.
  • HOZINU
    백엔드 탐험 일지
    HOZINU
  • 전체
    오늘
    어제
  • 블로그 메뉴

    • ⛪ HOME
    • 🌍 GITHUB
    • 카테고리 (73)
      • 1️⃣ 백앤드 (72)
        • 이펙티브 자바 (72)
      • 2️⃣ CS (0)
        • 운영체제 (0)
        • 네트워크 기초 (0)
        • 네트워크 응용 (0)
        • SSL & PKI (0)
        • 기타 (0)
      • 3️⃣ 코딩테스트 (0)
      • 4️⃣ 개인공부 (0)
        • MSA (0)
        • REDIS (0)
      • 5️⃣ 일상이야기 (1)
  • 인기 글

  • 태그

    멤버클래스
    의존객체
    캡슐화
    싱글턴
    Comparable
    계층구조
    로타입
    컴포지션
    표준예외
    hashcode
    try-with-resources
    optional
    Cleaner
    빌더
    정보은닉
    finalizer
    CLONE
    equals
    정적 팩터리 메서드
    맥북
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
HOZINU
[아이템16] public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라
상단으로

티스토리툴바