Item 22. 인터페이스는 타입을 정의하는 용도로만 사용하라

심규환·2022년 1월 29일
0

Effective Java

목록 보기
21/29

인터페이스는 자신을 구현한 클래스가 참조할 수 있는 타입 역할로만 사용해야 한다. 쉽게 말해 DI를 쓸 때 처럼, 인터페이스를 사용해서 구현 클래스를 담는 용도로 사용하고 클라이언트에 이 클래스의 인스턴스로 무엇을 할 수 있는지 설명하는 용도로만 사용해야 한다.

이런 인터페이스를 잘못 사용한 예가 상수 인터페이스이다. 타입으로만 쓰는게 아니라 상수를 담아서 제공하는 용도로 쓰는 것인데.

public interface PhysicalConstants{
	// 아보가드로 수
    static final double AVOGADROS_NUMBER = 6.022_140_857e23;
    // 볼츠만 상수
    static final double BOLTZMANN_CONSTANT = 1.380_648_52e-23;
  	// 전자 질량
    static final double ELECTRON_MASS = 9.109_383_56E-31;
}

뭔말인지 모르는 값들인데. 위의 인터페이스는 사용하면 안되는 예이다. 왜냐하면 클래스 내부에서 사용하는 상수는 클래스 내부 구현에 해당하기 때문이다. 이는 내부 구현을 클래스의 API로 노출하는 행위이다
이렇게 인터페이스로 제공한다면 클라이언트의 내부 구현들이 이 인터페이스의 상수 값에 종속되게 된다. 또 final이 아닌 클래스가 상수 인터페이스를 구현한다면 하위 클래스들은 이 인터페이스가 정의한 상수들로 오염되어 버린다.

만약 상수를 공개하고 제공할 목적이라면 아예 클래스를 하나 만들어라. 다음은 상수 유틸리티 클래스의 예이다.

public class PhysicalConstants{
    private PhysicalConstants(){} // 인스턴스 방지
    
    // 아보가드로 수
    static final double AVOGADROS_NUMBER = 6.022_140_857e23;
    // 볼츠만 상수
    static final double BOLTZMANN_CONSTANT = 1.380_648_52e-23;
  	// 전자 질량
    static final double ELECTRON_MASS = 9.109_383_56E-31;
}

그저 사용하고 싶다면 PhysicalConstants.AVOGADROS_NUMBER를 사용하면 된다. 내부 구현에 종속되지 않고 사용하고 싶을 때 사용하면 된다. 만약 너무 길다면 정적 임포트를 하여 클래스 이름을 생략할 수 있다.

profile
장생농씬가?

0개의 댓글