본문 바로가기

Java/Java

(JAVA) 클래스와 멤버의 접근 권한을 최소화하라

어설프게 설계된 컴포넌트와 잘 설계된 컴포넌트의 가장 큰 차이는 바로 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼느냐다.

https://jwdeveloper.tistory.com/175?category=830367

 

(OOP) 객체지향에 대해서(1) - 객체, 행동, 상태

객체지향에 대해서 대부분의 사람들은 이와 같이 생각한다. "객체지향이란 실세계를 직접적이고 직관적으로 모델링할 수 있는 패러다임" 과연 정말 실세계를 반영한 것일까? 예를 들자면 커피를 마시는 행위를 예..

jwdeveloper.tistory.com

https://effectiveprogramming.tistory.com/entry/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%A0%95%EB%B3%B4-%EC%9D%80%EB%8B%89information-hiding%EC%97%90-%EB%8C%80%ED%95%9C-%EC%98%AC%EB%B0%94%EB%A5%B8-%EC%9D%B4%ED%95%B4

 

객체지향의 올바른 이해 : 5. 정보 은닉(information hiding)

우리가 어떻게 해서 유연성을 확보할 수 있었는가? 그것은 추상화(Abstraction)에서부터 시작되었다. 추상화를 통해 우리는 여러 요구사항들 중에서 공통점을 찾고, 이 공통점에서 목표한 것과 관련 없는 것들을..

effectiveprogramming.tistory.com


정보은닉의 장점

  • 시스템 개발 속도를 높인다.
  • 시스템 관리 비용을 낮춘다. 
  • 성능 최적화에 도움을 준다. - 다른 컴포넌트에 영향을 주지 않고 특정 컴포넌트만 프로파일링 가능
  • 재사용성을 높인다.
  • 테스트가 쉬워진다.
가장 중요한 원칙
모든 클래스와 멤버의 접근성을 가능한 좁혀라

톱 레벨 클래스 : 파일명과 클래스명이 동일한 클래스

 

1. 패키지 외부에서 쓸 일이 없다면 package-private (default)로 선언하자

  • public으로 사용할 경우 외부에 공개되는 API가 되기 때문이다.
class topLevel {
    public static void main(String[] args) {
        nestedClass nestedClass = new topLevel.nestedClass();
        nestedClass.test();

    }

    private static class nestedClass {
        void test() {
            System.out.println("nested class starting....");
        }
    }
}

중첩 클래스를 private static으로 선언하면 해당 상위 클래스 밖에 접근하지 못하며 외부에서는 접근할 수 있는 방법이 없다.

 

2. 모든 멤버를 private을 사용하자

  • 패키지 외부에서 접근하는 멤버만 package-private으로 선언한다.
    • 만약 위의 상황이 반복된다면 컴포넌트를 조금 더 쪼개야 하지 않는가에 대해서 생각해보자

3. 메서드를 재정의 할 경우 접근 수준을 상위 클래스에서 보다 좁게 설정할 수 없다.

  • 하위 클래스의 메서드 접근 수준을 상위 클래스에서 보다 좁게 설정한다면 리스 코프 치환 원칙을 위반하는 행위이다. 
    • 상위 클래스에서 정의한 기능은 하위 클래스에서도 적용 가능해야 한다.
    • 인터페이스를 implements 하는 클래스는 예외 사항 - 클래스는 인터페이스가 정의한 메서드를 모두 private으로 선언한다.

자식의 접근제어자는 부모의 접근제어자 보다 좁게 설정할 수 없다.

public class Parent {
    
    public void test() {
        
    }
}
class Child extends Parent {
    //더 좁은 범위로 사용하였기 때문에 컴파일 오류 발생!
    @Override
    protected void test() {
        super.test();
    }
}

인터페이스의 구체 클래스의 접근제어자는 무조건 public

public interface ParentIml {
    void test();
}
class concreteChild2 implements ParentIml{
    /*부모는 private-package라도 자식은 항상 public으로 선언해야 한다.*/
    @Override
    public void test() {
        
    }
}

4. public 클래스의 인스턴스 필드는 public으로 선언하지 말자

public 가변 필드를 갖는 클래스는 일반적으로 Thread-Safety하지 않기 때문

 

상수라면 public static final 필드로 공개해도 좋다.

네이밍은 대문자_ 로 구성한다. 반드시 불변 객체를 참조하도록 한다.


5. 클래스에서 public static final 배열 필드를 두지 말자

public static testClass[] PRIVATE_VALUES = {};

 

testClass에 대한 참조는 바꿀 수 없지만 배열 내의 내용이 변경 가능하다.

 

해결책 1. 접근 제한자를 private으로 만들고 public 불변 리스트 만들기

private static testClass[] PRIVATE_VALUES = {};

public static final List<testClass> VALUES =
        Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));

해결책 2. 접근 제한자를 private으로 만들고 public메서드를 추가

private static testClass[] PRIVATE_VALUES = {};

public static final testClass[] values() {
    return PRIVATE_VALUES.clone();
}

References

이펙티브 자바 Effective Java 3/E
국내도서
저자 : 조슈아 블로크(Joshua Bloch) / 이복연(개앞맵시)역
출판 : 인사이트 2018.11.01
상세보기

https://jaehun2841.github.io/2019/01/19/effective-java-item15/#public-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%ED%95%84%EB%93%9C%EB%8A%94-%EB%90%98%EB%8F%84%EB%A1%9D-public%EC%9D%B4-%EC%95%84%EB%8B%88%EC%96%B4%EC%95%BC-%ED%95%9C%EB%8B%A4

 

Item 15. 클래스와 멤버의 접근 권한을 최소화하라 | Carrey`s 기술블로그

서론 잘 설계된 컴포넌트는 클래스는 모든 내부구현을 완벽히 숨겨, 구현과 API를 깔끔하게 분리 해놨다. 오직 API를 통해서만 다른 컴포넌트와 소통하며 서로의 내부 동작 방식에는 전혀 개의치 않는다. 정보은닉, 혹은 캡슐화라고 하는 이 개념은 소프트웨어 설계의 근간이 되는 원리다. 정보 은닉의 장점 시스템 개발 속도를 높인다. 여러가지 컴포넌트를 병렬로 개발할 수 있기 때문이다. 예를 들어, 회원탈퇴 기능을 개발한다고 해보자 123456789public

jaehun2841.github.io