Java를 배우고 있으며 인터페이스에 공개 정적 및 최종 필드가있을 수 있다는 것을 알았습니다. 나는 지금까지 이것들의 어떤 예도 보지 못했습니다. 이러한 인터페이스 상수의 사용 사례는 무엇이며 Java 표준 라이브러리에서 일부를 볼 수 있습니까?
답변
정적 멤버를 인터페이스에 배치 (및 해당 인터페이스 구현) 하는 것은 나쁜 습관 이며 이름 인 Constant Interface Antipattern 도 있습니다. 효과적인 Java , 항목 17을 참조하십시오 .
상수 인터페이스 패턴은 인터페이스를 제대로 사용하지 않는 것입니다 . 클래스가 내부적으로 일부 상수를 사용한다는 것은 구현 세부 사항입니다. 상수 인터페이스를 구현하면이 구현 세부 사항이 클래스의 내 보낸 API로 유출됩니다. 클래스가 상수 인터페이스를 구현하는 것은 클래스 사용자에게 중요하지 않습니다. 사실, 혼란 스러울 수도 있습니다. 더 나쁜 것은 약속을 나타냅니다. 향후 릴리스에서 더 이상 상수를 사용할 필요가 없도록 클래스가 수정되는 경우에도 이진 호환성을 보장하기 위해 인터페이스를 구현해야합니다. 최종 클래스가 아닌 클래스가 상수 인터페이스를 구현하는 경우 모든 하위 클래스는 인터페이스의 상수에 의해 네임 스페이스가 오염됩니다.
Java 플랫폼 라이브러리에는
java.io.ObjectStreamConstants
. 이러한 인터페이스는 이상 징후로 간주되어야하며 에뮬레이션해서는 안됩니다.
상수 인터페이스의 일부 함정을 피하려면 (사람들이 구현하는 것을 막을 수 없기 때문에) 개인 생성자가있는 적절한 클래스를 선호해야합니다 (예 : Wikipedia 에서 빌림 ).
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
정규화 할 필요없이 (즉, 클래스 이름을 접두사로 지정할 필요없이) 상수에 액세스하려면 정적 가져 오기 (Java 5부터)를 사용하십시오.
import static Constants.PLANCK_CONSTANT;
import static Constants.PI;
public class Calculations {
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT / (2 * PI);
}
}
답변
” 지속적인 인터페이스 패턴은 인터페이스를 잘 사용하지 않습니다. “
이 가설을 만든 사람은 누구든지 그 / 그녀가 전문가 일 수 있지만 나쁜 습관과 관행을 효율적으로 구현해야한다는 필요성을 기반으로 만들어졌습니다. 가설은 잘못된 소프트웨어 설계 습관의 타당성을 홍보하는 데 기반을두고 있습니다.
저는 여기에 그 가설에 대한 반박을 썼습니다. Java에서 상수를 구현하는 가장 좋은 방법은 무엇입니까? 이 가설의 근거 없음을 설명합니다.
내가이 가설을 정당화 한 이유를 게시 한 후 2 시간 이내에 그 질문이 닫힐 때까지 10 년 동안 그 질문은 열려 있었으며,이 잘못된 가설을 몹시 고수하는 사람들의 논쟁에 대한 UNWILLINGness를 드러 냈습니다.
이것이 제가 가설에 반하여 표현한 점입니다.
-
이 가설을 유지하는 기초는 나쁜 소프트웨어 습관과 방법론의 영향에 대처하기위한 방법과 제한적 규칙이 필요하다는 것입니다.
-
” 일관된 인터페이스 패턴은 인터페이스를 제대로 사용 하지 않는다 ” 라는 정서의 지지자들은 그러한 나쁜 습관과 관행의 영향에 대처할 필요가있는 이유 이외의 다른 이유를 제공 할 수 없습니다.
-
근본적인 문제를 해결하십시오.
-
그리고 Java 언어 구조의 모든 언어 기능을 최대한 활용하고 자신의 편의를 위해 활용하는 것은 어떻습니까? 재킷이 필요하지 않습니다. 왜 더 효과적인 라이프 스타일을 차별하고 유인하기 위해 당신의 비효율적 인 라이프 스타일을 막는 규칙을 발명합니까?
근본적인 문제
정보 조직입니다. 프로세스에 대한 솔루션을 엔지니어링하거나 보완하기 전에 프로세스를 매개하는 정보와 해당 정보의 동작을 소위 비즈니스 규칙과 함께 먼저 이해해야합니다. 이러한 정보 구성 방법은 수십 년 전에 데이터 정규화라고 불 렸습니다.
그러면 솔루션 구성 요소의 세분성 및 모듈성을 정보 구성 요소의 세분성 및 모듈 성과 일치시키는 것이 최적의 전략이기 때문에 솔루션의 엔지니어링 만 가능합니다.
정보를 구성하는 데 두세 가지 중요한 장애물이 있습니다.
-
데이터 모델 “정규화”의 필요성에 대한 인식 부족.
-
데이터 정규화에 대한 EF Codd의 진술은 결함이 있고 결함이 있으며 모호합니다.
-
애자일 엔지니어링으로 가장 한 최신 유행은 진행하면서 리팩토링 할 수 있기 때문에 앞으로의 모듈 구성을 계획하고 조정해서는 안된다는 잘못된 생각입니다. 미래의 발견에 지장을받지 않는 리팩토링과 지속적인 변화가 변명으로 사용됩니다. 프로세스 정보의 행동에 대한 필수적인 발견은 회계 속임수를 사용하여 수익과 자산화를 지연시키는 것입니다. 따라서 지금은 필수적인 지식과 그 처리가 필요하지 않은 것으로 간주됩니다.
인터페이스 상수를 사용하는 것이 좋습니다.
임시 뺑소니 프로그래밍 습관을 좋아한다고해서 규칙을 만들거나 그것에 반대하는 어떤 조치도하지 마십시오.
총을 다루는 방법을 모르거나 총을 남용하는 경향이있는 사람들이 있다는 이유로 총 소유권을 금지하지 마십시오.
당신이 만든 규칙이 전문적으로 코딩 할 수없는 프로그래밍 초보자를위한 것이고 그들 사이에서 당신 자신을 생각한다면 그렇게 말하십시오-당신의 fatwa를 적절하게 정규화 된 데이터 모델에 적용 할 수 있다고 선언하지 마십시오.
어리석은 추론-인터페이스는 그런 방식으로 사용되도록 자바 언어의 허풍에 의해 의도되지 않았습니까?
저는 미국 헌법에 대한 건국의 아버지들의 원래 의도가 무엇인지 상관하지 않습니다. 나는 문서화되지 않은 의도를 신경 쓰지 않는다. 나는 서면 헌법에 문자 적으로 성문화 된 내용과 사회의 효과적인 기능을 위해 어떻게 활용할 수 있는지에 만 관심이 있습니다.
저는 Java 언어 / 플랫폼 사양이 허용하는 것에 만 관심이 있고이를 최대한 활용하여 소프트웨어 솔루션을 효율적이고 효과적으로 표현할 수있는 매체를 제공 할 계획입니다. 재킷이 필요하지 않습니다.
Enum 상수의 사용은 실제로 끔찍한 연습입니다.
매개 변수를 값에 매핑하려면 추가 코드를 작성해야합니다. Java의 창립자가 사용자가 작성하지 않고는 매개 변수 값 맵핑을 제공하지 않았다는 사실은 맵핑 코드가 Enum 상수를 보여 준다는 사실은 의도하지 않은 Java 언어 사용과 같습니다.
특히 매개 변수를 정규화하고 구성 요소 화하도록 권장하지 않기 때문에 Enum 백에 혼합 된 매개 변수가 동일한 차원에 속한다는 잘못된 인상이있을 수 있습니다.
상수는 API 계약입니다.
잊지 마세요. 데이터 모델을 설계하고 정규화하고 여기에 상수가 포함 된 경우 해당 상수는 계약입니다. 데이터 모델을 정규화하지 않았다면 그 나쁜 습관에 대처하기 위해 제한적 코딩을 연습하는 방법에 대한 fatwas를 준수해야합니다.
따라서 인터페이스는 Constants의 계약을 구현하는 완벽한 방법입니다.
이상한 추정-인터페이스가 우연히 구현되면 어떨까요?
예. 누구나 실수로 인터페이스를 실수로 구현할 수 있습니다. 그러한 부주의 한 프로그래머를 방해하는 것은 없습니다.
누출에 대한 데이터 모델 설계 및 정규화
계약되지 않은 / 잘못된 매개 변수가 API로 유출되는 원인이 될 것으로 추정되는 나쁜 관행을 보호하기 위해 제한적인 법령을 두지 마십시오. 인터페이스 상수를 비난하기보다는 근본적인 문제를 해결하십시오.
IDE를 사용하지 않는 것은 나쁜 습관입니다
정상적인 기능과 효과적인 프로그래머는 그녀가 수중에 얼마나 오래 머물 수 있는지, 맹렬한 더위 나 습한 뇌우 속에서 얼마나 멀리 걸을 수 있는지 증명하기 위해 거기에 있지 않습니다. 그녀는 매일 10 마일을 일하기 위해 자동차 나 버스 또는 최소한 자전거와 같은 효율적인 도구를 사용해야합니다.
IDE없는 프로그래밍에 대한 난해한 금욕주의에 집착한다고해서 동료 프로그래머에게 제한을 두지 마십시오.
프로그래머가 나쁜 습관을 효율적으로 계속 연습 할 수 있도록 몇 가지 프레임 워크가 설계되었습니다.
OSGI는 그러한 프레임 워크입니다. 인터페이스 상수에 대한 법령도 마찬가지입니다.
따라서 결정적인 대답은 …
인터페이스 상수는 데이터 모델의 잘 디자인되고 정규화 된 구성 요소를 계약에 배치하는 효과적이고 효율적인 방법입니다.
클래스 파일에 중첩 된 적절하게 이름이 지정된 개인 인터페이스의 인터페이스 상수는 파일 전체에 분산되지 않고 모든 개인 상수를 그룹화하는 좋은 방법입니다.
답변
나는이 오래된 질문을 여러 번 보았고 받아 들여지는 대답은 여전히 나를 혼란스럽게합니다. 많은 생각 끝에이 질문이 더 명확해질 수 있다고 생각합니다.
인터페이스 상수를 사용하는 이유는 무엇입니까?
비교해보세요.
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
vs
public interface Constants {
double PI = 3.14159;
double PLANCK_CONSTANT = 6.62606896e-34;
}
같은 사용법. 훨씬 적은 코드.
나쁜 습관?
@Pascal Thivent의 답변에 잘못된 강조가 있다고 생각합니다. 여기에 내 버전이 있습니다.
정적 멤버를 인터페이스에 넣고 해당 인터페이스 를 구현하는 것은 나쁜 습관입니다.
Effective Java의 인용문에는 다른 사람들이 지속적인 인터페이스를 구현하고 있다는 가정이 있습니다.
과 같은 이름의 상수 인터페이스를 만들 때 Constants
누구도 구현해서는 안됩니다. (기술적으로 가능하지만 여기서 유일한 문제입니다)
표준 라이브러리에서는 발생하지 않습니다.
표준 라이브러리는 디자인의 오용 가능성을 감당할 수 없으므로 거기에서 아무것도 볼 수 없습니다.
그러나 일반 개발자의 일상적인 프로젝트의 경우 상수 인터페이스를 사용하는 것이 훨씬 쉽습니다 static
. final
,,empty constructor
, 등, 그리고 어떤 나쁜 디자인의 문제가 발생하지 않습니다. 내가 생각할 수있는 유일한 단점은 여전히 ”인터페이스”라는 이름이 있지만 그 이상은 없다는 것입니다.
끝없는 논쟁
결국 나는 모든 사람들이 책을 인용하고 그들의 입장에 대한 의견과 정당성을 부여한다고 생각합니다. 나를위한 예외는 없습니다. 결정은 여전히 각 프로젝트의 개발자에게 달려 있습니다. 당신이 편안하다고 느끼면 계속 사용하십시오. 우리가 할 수있는 최선 은 프로젝트 전체에서 일관성을 유지하는 것 입니다.
답변
Joshua Bloch, “Effective Java-Programming Language Guide”:
상수 인터페이스 패턴은 인터페이스를 제대로 사용하지 않는 것입니다. 클래스가 내부적으로 일부 상수를 사용한다는 것은 구현 세부 사항입니다. 상수 인터페이스를 구현하면이 구현 세부 사항이 클래스의 내 보낸 API로 유출됩니다. 클래스가 상수 인터페이스를 구현하는 것은 클래스 사용자에게 중요하지 않습니다. 사실, 혼란 스러울 수도 있습니다. 더 나쁜 것은 약속을 나타냅니다. 향후 릴리스에서 더 이상 상수를 사용할 필요가 없도록 클래스가 수정되는 경우에도 이진 호환성을 보장하기 위해 인터페이스를 구현해야합니다. 최종 클래스가 아닌 클래스가 상수 인터페이스를 구현하는 경우 모든 하위 클래스는 인터페이스의 상수에 의해 네임 스페이스가 오염됩니다.
답변
인터페이스를 구현하는 클래스에서 사용될 공통 상수가있는 경우 유용합니다.
예 :
http://www.javapractices.com/topic/TopicAction.do?Id=32
그러나 권장되는 방법은 인터페이스에서 상수 대신 정적 가져 오기를 사용하는 것입니다. 다음은 참조입니다. http://www.javapractices.com/topic/TopicAction.do?Id=195
답변
매우 공감하는 답변이 있습니다.
하지만이 질문에 대해 몇 가지 생각이 있습니다. (틀릴 수 있음)
제 생각에, 인터페이스의 필드는 전체 프로젝트에 대한 상수가 아니어야합니다. 그것들은 인터페이스를위한 수단 일 뿐이며 인터페이스는 인터페이스를 확장하고 이러한 인터페이스를 구현하거나 그들과 밀접한 관계를 갖는 클래스입니다. 글로벌이 아닌 특정 범위 내에서 사용해야합니다.
답변
인터페이스에 대한 두 가지 사항 :
-
인터페이스는 이 를 구현 하는 객체 가 수행 할 수있는 작업 의 하위 집합 을 설명 합니다 . (이것이 직감입니다)
-
인터페이스는이 를 구현하는 객체 가 따르는 공통 상수를 설명 합니다.
- 이러한 공통 상수 는 이러한 객체에 대해 더 많이 알기 위해 클라이언트가 알 수 있도록 고안 되었습니다.
- 그래서 상수 인터페이스는 참으로 정의하는 직관적 인 글로벌 상수 인터페이스를 설명하는 데 사용되기 때문에, 일부 개체 가 아닌 모든 개체를 / 어떤 객체 (의 의미를 고려하지 글로벌을 ).
따라서 Constants Interface 가 전역 상수에 사용되지 않으면 허용됩니다.
- 이러한 공통 상수 에 좋은 이름 이 있으면 구현 자에게 사용하도록 권장 합니다 (아래 예제에 대한 첫 번째 요점 참조).
- 클래스가 사양을 따르는 클래스와 동기화하려는 경우 해당 클래스 만 동기화
implements
합니다 (물론 구현시 이러한 공통 상수를 사용합니다).
예:
interface Drawable {
double GOLDEN_RATIO = 1.618033988;
double PI = 3.141592653;
...
// methods
...
}
public class Circle implements Drawable {
...
public double getCircumference() {
return 2 * PI * r;
}
}
void usage() {
Circle circle = new Circle(radius: 3.0);
double maxRadius = 5.0;
if ( circle.getCircumference() < 2 * Circle.PI * maxRadius ) {
...
}
}
이 예에서 :
- 에서
Circle implements Drawable
, 당신은 바로 그 아는Circle
아마에 정의 된 상수에 따른다Drawable
그렇지 않으면 좋은 것들 때문에 더 나쁜 이름을 선택해야PI
하고GOLDEN_RATIO
이미 촬영되었습니다! - 만 이러한
Drawable
오브젝트는 특정을 준수PI
하고GOLDEN_RATIO
정의Drawable
없는,있을 수있는 개체Drawable
파이와 황금 비율의 다른 정밀.