본문 바로가기
책/effective java

[effective java] item 22. 인터페이스는 타입을 정의하는 용도로만 사용하라

by 2245 2023. 8. 21.

결론

인터페이스는 타입을 정의하는 용도로만 사용해야 합니다.
상수 공개용 수단으로 사용하면 안 됩니다.
인터페이스의 대안으로 특정 클래스나 인터페이스와 강하게 연관된 상수의 경우 클래스 및 인터페이스 내부에 상수 선언, 열거 타입 사용, 유틸리티 클래스가 있습니다. 

 

 

설명

인터페이스는 클래스의 인스턴스를 참조할 수 있는 타입 역할을 말합니다. 인터페이스는 오직 이러한 타입을 정의하는 용도로만 사용해야 합니다.

 

 

인터페이스의 잘못된 사용 : 상수 인터페이스

이 지침에 맞지 않는 예로 상수 인터페이스라는 것이 있습니다.

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

그리고 이 상수들을 사용하려는 클래스에서는 정규화된 이름을 쓰는 걸 피하고자 그 인터페이스를 구현하곤 합니다.

 

public interface PhysicalConstants {
    public static final double AVOGADROS_NUMBER = 6.022_140_857e23;
    public static final double BOLTZMANN_CONST = 1.380_648_52e-23;
    public static final double ELECTRON_MASS = 9.109_383_56e-31;
}
public class MyClass implements PhysicalConstants {
    double AVO = PhysicalConstants.AVOGADROS_NUMBER;
	double BOL = PhysicalConstants.BOLTZMANN_CONST;
}

 

이러한 상수 인터페이스를 사용하는 것은 몇 가지 단점이 있습니다.

 

문제점 1. 클래스와 인터페이스의 목적 혼동

인터페이스는 주로 다형성을 지원하고 클래스의 동작을 규정하는 데 사용됩니다.

상수 인터페이스를 사용하면 클래스의 목적과 인터페이스의 목적이 혼동될 수 있습니다.

 

문제점 2. 내부 구조 노출

클래스 내부에서 사용하는 상수는 외부 인터페이스가 아니라, 내부 구현에 해당합니다. 

따라서, 상수 인터페이스를 구현하는 것은 내부 구현을 클래스의 API로 노출하는 행위입니다.

 

이는 클라이언트 코드가 내부 구현에 해당하는 이 상수들에 종속되게 합니다.

따라서 다음 릴리스에서 이 상수들을 더는 쓰지 않게 되더라도 호환성을 위해 여전히 상수 인터페이스를 구현하고 있어야 합니다. 

 

문제점 3. 하위 클래스의 이름 공간 오염

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

 

public interface TestInterFace {
    static String NAME = "incheol";
}

public class InterfaceImpl implements TestInterFace {

    public static void main(String[] args) {
        System.out.println(NAME);		//incheol
    }
}

public class InterfaceImpl implements TestInterFace {
    public static final String NAME = "test";

    public static void main(String[] args) {
        System.out.println(NAME);		//test
    }
}

(출처 : https://incheol-jung.gitbook.io/docs/study/effective-java/undefined-2/2020-03-20-effective-22item)

 

 

상수 인터페이스의 대안

1. 특정 클래스나 인터페이스와 강하게 연관된 상수의 경우 : 그 클래스나 인터페이스 자체에 추가합니다. 

ex) Integer와 Double에 선언된 MIN_VALUE와 MAX_VALUE 상수

 

 

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

public enum Day{ MON, TUE, WED, THU, FRI, SAT, SUN};

 

3. 아니라면, 인스턴스화할 수 없는 유틸리티 클래스에 담아 공개합니다. 

 

PhysicalConstants 상수 유틸리티 클래스

public class PhysicalConstants {
	private PhysicalConstants() {} 		//private 생성자 -> 인스턴스화 방지
    
    public static final double AVOGADROS_NUMBER = 6.022_140_857e23;
    public static final double BOLTZMANN_CONST = 1.380_648_52e-23;
    public static final double ELECTRON_MASS = 9.109_383_56e-31;
}

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

ex) PhysicalConstants.AVOGADROS_NUMBER 

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

 

정적 임포트를 사용해 상수 이름만으로 사용하기

import class effectivejava.chapter4.item22.PhysicalConstants.*;
//PhysicalConstants를 빈번히 사용한다면 정적 임포트가 값어치를 한다. 

public class Test {
	double atoms(double mols) {
    	return AVOGADROS_NUMBER * mols;
    }
}

 

 


출처

https://www.yes24.com/Product/Goods/65551284

 

이펙티브 자바 Effective Java 3/E - 예스24

자바 플랫폼 모범 사례 완벽 가이드 - Java 7, 8, 9 대응자바 6 출시 직후 출간된 『이펙티브 자바 2판』 이후로 자바는 커다란 변화를 겪었다. 그래서 졸트상에 빛나는 이 책도 자바 언어와 라이브

www.yes24.com