Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

README.md

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

책정리

아이템34
아이템4

인터페이스

인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할을 한다.

→ 클래스가 어떤 인터페이스를 구현한다는 것은 자신의 인스턴스로 무엇을 할 수 있는지를 클라이언트에 얘기해주는 것이다.

안티패턴 예시

상수 인터페이스

상수 인터페이스는 메서드 없이, 상수를 뜻하는 static final 필드로만 가득 찬 인터페이스를 말한다.

→ 정규화된 이름(qualified name)을 쓰는 걸 피하고자 인터페이스를 구현하곤 한다.

public interface PhysicalConstants {
    static final double AVOGADROS_NUMBER = 6.022_140_857e23;
    
		....    
}

클래스 내부에서 사용하는 상수는 외부 인터페이스가 아니라 내부 구현에 해당한다. 상수 인터페이스를 구현하는 것은 이 내부 구현을 클래스의 API로 노출하는 행위다.

클래스가 어떤 상수 인터페이스를 사용하든 사용자에게 오히려 혼란을 주고, 심하게는 클라이언트 코드가 내부 구현에 해당하는 이 상수들에 종속되게 한다.

final이 아닌 클래스가 상수 인터페이스를 구현한다면 모든 하위 클래스의 이름공간이 그 인터페이스가 정의한 상수들로 오염된다.

ex) java.io.ObjectStreamConstants...

상수 공개하는 선택지

특정 클래스나 인터페이스와 강하게 연관된 상수라면 그 클래스나 인터페이스 자체에 추가해야 한다.

모든 숫자 기본 타입의 박싱 클래스가 대표적으로, Integer와 Double에 선언된 MIN_VALUE, MAX_VALUE 상수가 예시다.

열거 타입으로 나타내기 적합한 상수라면 열거 타입으로 만들어 공개하면 된다.

또는, 인스턴스화 할 수 없는 유틸리티 클래스에 담아 공개하면 된다.

// 유틸리티 클래스
public class PhysicalConstants {
    private PhysicalConstants() {}
    public static final double AVOGADROS_NUMBER = 6.022_140_857e23;

		...
}

유틸리티 클래스에 정의된 상수를 클라이언트에서 사용하려면 클래스 이름까지 명시해야 한다.

→ PhysicalConstants.AVOGADROS_NUMBER

유틸리티 클래스의 상수를 빈번히 사용한다면 정적 임포트(static import)하여 클래스 이름은 생략할 수 있다.

결론

인터페이스는 타입을 정의하는 용도로만 사용해야 한다. 상수 공개용 수단으로 사용하지 말자

Q&A

ObjectStreamConstants 왜 만들었을까?

  • 실수
  • 설계상 잘못 되긴 했지만, 삭제함으로써 발생하는 문제를 방지하기 위해서 굳이 지우진 않는듯.