Enum이 인터페이스를 구현하는 이유는 무엇입니까?
자바에서는 enums가 인터페이스를 구현할 수 있다는 것을 방금 알게 되었습니다.어떤 활용 사례가 좋을까요?
다음은 예를 제시하겠습니다(유효한 Java 2nd Edition에 유사한/더 나은 예가 나와 있습니다).
public interface Operator {
int apply (int a, int b);
}
public enum SimpleOperators implements Operator {
PLUS {
int apply(int a, int b) { return a + b; }
},
MINUS {
int apply(int a, int b) { return a - b; }
};
}
public enum ComplexOperators implements Operator {
// can't think of an example right now :-/
}
이제 Simple + Complex 연산자 목록을 얻으려면 다음 절차를 수행합니다.
List<Operator> operators = new ArrayList<Operator>();
operators.addAll(Arrays.asList(SimpleOperators.values()));
operators.addAll(Arrays.asList(ComplexOperators.values()));
여기서는 인터페이스를 사용하여 확장 가능한 Enum을 시뮬레이션합니다(인터페이스를 사용하지 않으면 불가능).
에넘은 수동 세트(예: 색상)를 나타낼 필요가 없습니다. 오브젝트는 기능이 보다 수 있기 이러한 오브젝트에 할 수 를 들어, 예를 들어, 오브젝트에는 다음과 같은 수 있습니다.예를 들어 다음과 같은 인터페이스가 있을 수 있습니다.Printable,Reportable이를 지원하는 컴포넌트 등입니다.
Comparable여기 있는 몇몇 사람들에 의해 주어진 예는 틀렸다, 왜냐하면 왜냐하면Enum이미 구현되어 있습니다.넌 그걸 무시할 수도 없어.
예를 들어 데이터 유형을 정의하는 인터페이스를 사용하는 것이 좋습니다.단순 유형을 구현하는 열거형 및 복잡한 유형을 구현하는 일반 클래스를 가질 수 있습니다.
interface DataType {
// methods here
}
enum SimpleDataType implements DataType {
INTEGER, STRING;
// implement methods
}
class IdentifierDataType implements DataType {
// implement interface and maybe add more specific methods
}
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★는 나나 a a a가 있다IdUtil 한 오브젝트를 Identifiable★★★★★★★★★★★★★★★★★★:
public interface Identifiable<K> {
K getId();
}
public abstract class IdUtil {
public static <T extends Enum<T> & Identifiable<S>, S> T get(Class<T> type, S id) {
for (T t : type.getEnumConstants()) {
if (Util.equals(t.getId(), id)) {
return t;
}
}
return null;
}
public static <T extends Enum<T> & Identifiable<S>, S extends Comparable<? super S>> List<T> getLower(T en) {
List<T> list = new ArrayList<>();
for (T t : en.getDeclaringClass().getEnumConstants()) {
if (t.getId().compareTo(en.getId()) < 0) {
list.add(t);
}
}
return list;
}
}
내가 '만들기'를,Identifiable enum:
public enum MyEnum implements Identifiable<Integer> {
FIRST(1), SECOND(2);
private int id;
private MyEnum(int id) {
this.id = id;
}
public Integer getId() {
return id;
}
}
그럼 내가 그걸 손에 넣을 수 있어id 방법 명령어:
MyEnum e = IdUtil.get(MyEnum.class, 1);
Enums는 인터페이스를 구현할 수 있기 때문에 싱글톤 패턴의 엄격한 적용에 사용할 수 있습니다.싱글톤이 허용하는 스탠다드 클래스를 만들기 위해...
- 성찰 기법을 사용하여 개인 방법을 공개하는 가능성
- 당신의 싱글톤으로부터 물려받아 당신의 싱글톤 방식을 다른 무언가로 덮어쓰기 위해
enums as singleton은 이러한 보안 문제를 방지하는 데 도움이 됩니다.이것이 Enums가 클래스로서 동작해 인터페이스를 실장하도록 하는 주된 이유 중 하나였을 가능성이 있습니다.그냥 추측하는 거야.
자세한 내용은 https://stackoverflow.com/questions/427902/java-enum-singleton 및 Java의 Singleton 클래스를 참조하십시오.
확장성에 필요합니다.다른 사용자가 개발한 API를 사용하는 경우 정의한 enum은 정적이므로 추가 또는 수정할 수 없습니다.그러나 인터페이스를 구현하도록 허용하면 API를 사용하는 사용자는 동일한 인터페이스를 사용하여 자체 열거형을 개발할 수 있습니다.그런 다음 Enum 매니저에 이 Enum을 등록할 수 있습니다.Enum 매니저는 Enum을 표준 인터페이스와 함께 결합합니다.
Edit: @Helper Method에는 이에 대한 완벽한 예가 있습니다.다른 라이브러리에서 새 연산자를 정의하고 관리자 클래스에 '이 열거형이 존재합니다. 등록하십시오.'라고 말하는 경우를 생각해 보십시오.그렇지 않으면 사용자 고유의 코드로 연산자를 정의할 수 있을 뿐 확장성은 없습니다.
전술한 전략에서는, enum을 사용한 전략 패턴의 경량의 실장이 가져오는 메리트를 충분히 강조하지 않았습니다.
public enum Strategy {
A {
@Override
void execute() {
System.out.print("Executing strategy A");
}
},
B {
@Override
void execute() {
System.out.print("Executing strategy B");
}
};
abstract void execute();
}
각각의 컴파일 유닛이 따로 필요 없이 모든 전략을 한 곳에서 실행할 수 있습니다.다음의 기능만으로, 다이나믹한 디스패치가 가능하게 됩니다.
Strategy.valueOf("A").execute();
java를 거의 맛있고 느슨하게 타이핑된 언어처럼 읽을 수 있게 합니다!
enum은 위장된 클래스일 뿐이므로 대부분의 경우 클래스에서 수행할 수 있는 모든 작업을 열거형으로 수행할 수 있습니다.
열거형이 인터페이스를 구현할 수 없는 이유를 생각할 수 없고 동시에 구현해야 하는 타당한 이유도 생각할 수 없습니다.
인터페이스나 메서드 등을 열거형에 추가하기 시작하면 그 대신 클래스로 만드는 것을 고려해야 합니다.물론 전통적인 열거형 이외의 것을 할 수 있는 유효한 케이스가 있다고 생각합니다.한계는 인위적인 것이기 때문에, 나는 사람들이 거기서 하고 싶은 것을 하도록 하는 것에 찬성합니다.
예를 들어 Logger 열거형이 있는 경우.다음으로 인터페이스에 debug, info, warning, error 등의 logger 메서드를 설정합니다.코드를 느슨하게 결합시킵니다.
가장 일반적인 방법은 두 Enum 값을 하나의 그룹으로 병합하여 동일하게 처리하는 것입니다.예를 들어, 과일과 채소에 가입하는 방법을 참조하십시오.
인터페이스와 함께 열거형을 사용하는 가장 좋은 사용 사례 중 하나는 Predicate 필터입니다.아파치 컬렉션의 유형 부족을 해결하는 매우 우아한 방법입니다(다른 라이브러리를 사용할 수 없는 경우).
import java.util.ArrayList;
import java.util.Collection;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
public class Test {
public final static String DEFAULT_COMPONENT = "Default";
enum FilterTest implements Predicate {
Active(false) {
@Override
boolean eval(Test test) {
return test.active;
}
},
DefaultComponent(true) {
@Override
boolean eval(Test test) {
return DEFAULT_COMPONENT.equals(test.component);
}
}
;
private boolean defaultValue;
private FilterTest(boolean defautValue) {
this.defaultValue = defautValue;
}
abstract boolean eval(Test test);
public boolean evaluate(Object o) {
if (o instanceof Test) {
return eval((Test)o);
}
return defaultValue;
}
}
private boolean active = true;
private String component = DEFAULT_COMPONENT;
public static void main(String[] args) {
Collection<Test> tests = new ArrayList<Test>();
tests.add(new Test());
CollectionUtils.filter(tests, FilterTest.Active);
}
}
또 다른 장점:
public enum ConditionsToBeSatisfied implements Predicate<Number> {
IS_NOT_NULL(Objects::nonNull, "Item is null"),
IS_NOT_AN_INTEGER(item -> item instanceof Integer, "Item is not an integer"),
IS_POSITIVE(item -> item instanceof Integer && (Integer) item > 0, "Item is negative");
private final Predicate<Number> predicate;
private final String notSatisfiedLogMessage;
ConditionsToBeSatisfied(final Predicate<Number> predicate, final String notSatisfiedLogMessage) {
this.predicate = predicate;
this.notSatisfiedLogMessage = notSatisfiedLogMessage;
}
@Override
public boolean test(final Number item) {
final boolean isNotValid = predicate.negate().test(item);
if (isNotValid) {
log.warn("Invalid {}. Cause: {}", item, notSatisfiedLogMessage);
}
return predicate.test(item);
}
}
및 사용방법:
Predicate<Number> p = IS_NOT_NULL.and(IS_NOT_AN_INTEGER).and(IS_POSITIVE);
jar 파일에 상수를 작성할 때 사용자가 열거값을 확장할 수 있도록 하는 것이 도움이 되는 경우가 많습니다.Property File 키에 enum을 사용했는데 아무도 새 키를 추가할 수 없어 꼼짝할 수 없습니다.아래가 훨씬 더 잘 작동했을 것입니다.
지정:
public interface Color {
String fetchName();
}
또, 다음과 같이 합니다.
public class MarkTest {
public static void main(String[] args) {
MarkTest.showColor(Colors.BLUE);
MarkTest.showColor(MyColors.BROWN);
}
private static void showColor(Color c) {
System.out.println(c.fetchName());
}
}
항아리에는 다음과 같은 열거형이 있을 수 있습니다.
public enum Colors implements Color {
BLUE, RED, GREEN;
@Override
public String fetchName() {
return this.name();
}
}
사용자가 확장하여 자신만의 색상을 추가할 수 있습니다.
public enum MyColors implements Color {
BROWN, GREEN, YELLOW;
@Override
public String fetchName() {
return this.name();
}
}
Enum은 Java 클래스와 비슷하며 생성자, 메서드 등을 가질 수 있습니다.그들과 함께 할 수 없는 유일한 것은new EnumName()인스턴스는 열거형 선언에 미리 정의되어 있습니다.
이게 내가 왜...
JavaFX ComboBox에 Enum 값을 입력했습니다.Identifyable(Identify) 인터페이스가 있어 검색 목적으로 응용 프로그램에서 개체를 식별하는 방법을 지정할 수 있습니다.이 인터페이스를 사용하면 ID 조회를 위해 오브젝트 유형(개체가 ID에 사용할 수 있는 필드 중 하나)의 목록을 검색할 수 있습니다.
내 ComboBox 목록에서 ID 값과 일치하는 항목을 찾고 싶습니다.Enum 값을 포함하는 ComboBox에서 이 기능을 사용하려면 Enum에 Identifyable 인터페이스를 구현할 수 있어야 합니다(Enum의 경우 구현이 간단함).
인터페이스에서 inner enum을 사용하여 인스턴스 제어(각 전략은 싱글톤)를 유지하는 전략을 설명했습니다.
public interface VectorizeStrategy {
/**
* Keep instance control from here.
*
* Concrete classes constructors should be package private.
*/
enum ConcreteStrategy implements VectorizeStrategy {
DEFAULT (new VectorizeImpl());
private final VectorizeStrategy INSTANCE;
ConcreteStrategy(VectorizeStrategy concreteStrategy) {
INSTANCE = concreteStrategy;
}
@Override
public VectorImageGridIntersections processImage(MarvinImage img) {
return INSTANCE.processImage(img);
}
}
/**
* Should perform edge Detection in order to have lines, that can be vectorized.
*
* @param img An Image suitable for edge detection.
*
* @return the VectorImageGridIntersections representing img's vectors
* intersections with the grids.
*/
VectorImageGridIntersections processImage(MarvinImage img);
}
enum 클래스가 폐쇄된 인스턴스의 프록시 역할을 할 수 있도록 하기 위해 enum 클래스가 전략을 구현하는 것이 편리합니다.인터페이스도 실장합니다.
strategyEnumProxy :P 의 일종입니다.클런트 코드는 다음과 같습니다.
VectorizeStrategy.ConcreteStrategy.DEFAULT.processImage(img);
인터페이스가 실장되어 있지 않은 경우는, 다음과 같습니다.
VectorizeStrategy.ConcreteStrategy.DEFAULT.getInstance().processImage(img);
언급URL : https://stackoverflow.com/questions/2709593/why-would-an-enum-implement-an-interface
'source' 카테고리의 다른 글
| 네임스페이스가 다른 유사한 이름의 vue/vuex mapActions 메서드에 액세스하는 방법 (0) | 2022.08.21 |
|---|---|
| Vue 하위 구성 요소 속성이 작동하지 않음 (0) | 2022.08.21 |
| gitlab-ci에서의 VueJS 앱 e2e 테스트 (0) | 2022.08.20 |
| 일정 동작을 에뮬레이트하기 위해 닫힘 태그를 조건부로 렌더링합니다. (0) | 2022.08.20 |
| vee-validate와 함께 작동하도록 커스텀 입력 컴포넌트를 수정하는 방법 (0) | 2022.08.20 |