簡體   English   中英

Java:具有具體實現的抽象枚舉

[英]Java: Abstract enum with concrete implementations

有沒有辦法根據枚舉名稱創建具有不同值的枚舉抽象?

這是一個 class ,我會發現類似抽象枚舉的東西很有用:

public class StatusUpdater {
public foo(bool one, bool two, bool three, AbstractEnum status) {
    if (one) {
        caseOne(status);
    }

    if (two) {
        caseTwo(status);
    }

    if (three) {
        caseThree(status);
    }
}

private void caseOne(CaseOneEnum status) {
    status.getValue(); //return case one value + case one implementation
}

private void caseTwo(CaseTwoEnum status) {
    status.getValue(); //return case two value + case two implementation
}

private void caseThree(CaseThreeEnum status) {
    status.getValue(); //return case three value + case three implementation
}

}

枚舉的具體實現之一如下所示:

public enum CaseOneEnum {
STATUS_ONE("one"),
STATUS_TWO("two");

private final String status;

CaseOneEnum(final String status) {
    this.status = status;
}

@Override
String getValue(){return status;}

另一個實現將具有相同的枚舉名稱,但不同的值:

public enum CaseTwoEnum {
STATUS_ONE("oneTwo"),
STATUS_TWO("twoTwo");

private final String status;

CaseTwoEnum(final String status) {
    this.status = status;
}

@Override
String getValue(){return status;}

調用 main 方法應該如下所示:

updater.foo(true, true, false, AbstractEnum.STATUS_ONE);

有沒有一種方法可以創建一些“抽象”枚舉,我可以將其傳遞給 foo() 並在檢查案例后采取該枚舉的具體實現。 所有具體枚舉的枚舉名稱將保持不變,但值會有所不同。 我會想象一個像這樣的“抽象”枚舉:

public enum AbstractEnum {
STATUS_ONE,
STATUS_TWO;

@Override
String getValue();

有沒有辦法以一種簡潔的方式實現類似的目標?

實際上,所有枚舉都是 object 枚舉的后代,這已經構成了一個泛型類型,您可以使用它來實現獨立於實際枚舉實現的方法簽名。

然后,您的代碼顯示,對於每個“案例”,您確切地知道期望哪個枚舉,因此您可以在調用專用方法時簡單地class 轉換輸入 object 。

我拿走了您的代碼並對其進行了一些修改以演示我的建議。

兩個枚舉實現

public enum CaseOneEnum {
    STATUS_ONE("one"),
    STATUS_TWO("two");

    private final String status;

    CaseOneEnum(final String status) {
        this.status = status;
    }

    String getValue() {
        return status;
    }
}

public enum CaseTwoEnum {
     STATUS_THREE("three"),
     STATUS_FOUR("four");

     private final String status;

     CaseTwoEnum(final String status) {
         this.status = status;
     }

     String getValue() {
         return status;
     }
 }

StatusUpdater class

public class StatusUpdater {

    public String foo(int caze, Enum<?> status) {

        if (caze == 1) {
            return caseOne((CaseOneEnum) status);
        }

        if (caze == 2) {
            return caseTwo((CaseTwoEnum) status);
        }
        return null;
    }

    private String caseOne(CaseOneEnum status) {
        return status.getValue();
    }

    private String caseTwo(CaseTwoEnum status) {
        return status.getValue();
    }
}

需要注意的最重要的事情是 foo 方法簽名公開了Enum類型的參數,以及在調用每個 case 方法時的class 強制轉換

最后用 JUnit 來演示。

public class StatusUpdaterTest {

    @Test
    public void testStatusUpdaterCase1() {
        StatusUpdater updater = new StatusUpdater();
        assertEquals(CaseOneEnum.STATUS_ONE.getValue(), updater.foo(1, CaseOneEnum.STATUS_ONE));
}

    @Test
    public void testStatusUpdaterCase2() {
        StatusUpdater updater = new StatusUpdater();
        assertEquals(CaseOneEnum.STATUS_TWO.getValue(), updater.foo(1, CaseOneEnum.STATUS_TWO));
    }

    @Test
    public void testStatusUpdaterCase3() {
        StatusUpdater updater = new StatusUpdater();
        assertEquals(CaseTwoEnum.STATUS_THREE.getValue(), updater.foo(2, CaseTwoEnum.STATUS_THREE));
    }

    @Test
    public void testStatusUpdaterCase4() {
        StatusUpdater updater = new StatusUpdater();
        assertEquals(CaseTwoEnum.STATUS_FOUR.getValue(), updater.foo(2, CaseTwoEnum.STATUS_FOUR));
    }
}

希望這可以幫助!

干杯

這是使用接口的解決方案。 因為枚舉可以實現接口,所以您可以擺脫重載的方法(除非它們的實現不同)。

interface MyEnumInterface {
    String getValue();
}

這樣,您的 StatusUpdater class 變為:

public class StatusUpdater {
    public void foo(MyEnumInterface status) {
        anyCase(status);
    }

    //You can duplicate this with caseOne, caseTwo methods if
    //implementations are actually different
    private void anyCase(MyEnumInterface status) {
        status.getValue(); 
    }
}

然后你以這種方式調用你的foo方法:

updater.foo(1, CaseOneEnum.STATUS_ONE);
updater.foo(1, CaseTwoEnum.STATUS_ONE);

然后剩下的就是讓你的枚舉實現接口(他們已經有了方法):

enum CaseOneEnum implements MyEnumInterface {
    STATUS_ONE("one"), 
    STATUS_TWO("two");

    private final String status;

    CaseOneEnum(final String status) {
        this.status = status;
    }

    @Override
    public String getValue() {
        return status;
    }
}

//other enums implement the

您正在混淆定義常量和相關數據的枚舉。 你想定義一個“抽象枚舉”的原因是,只有一組常量,所以實際的結論是應該只有一個enum

雖然enum類型允許直接保存關聯數據,但您應該將此功能僅用於規范關聯。 當像您的情況一樣,有不同的關聯數據集時,您不應該將它們存儲在enum類型中,因為它只允許一對一的關系。 此外,不是創建另一個定義相同常量的冗余enum類型,而是將數據存儲在EnumMap中,該 EnumMap 專門用於將數據與enum常量相關聯。

定義一個簡單的enum類型為

public enum YourActualEnum {
    STATUS_ONE,
    STATUS_TWO
}

以及具有不同關聯數據的 class ,具體取決於用例:

public class StatusUpdater {
    private static final EnumMap<YourActualEnum,String> CASE1, CASE2, CASE3;
    static {
        CASE1 = new EnumMap<>(YourActualEnum.class);
        CASE1.put(YourActualEnum.STATUS_ONE, "one");
        CASE1.put(YourActualEnum.STATUS_TWO, "two");
        CASE2 = new EnumMap<>(YourActualEnum.class);
        CASE2.put(YourActualEnum.STATUS_ONE, "oneTwo");
        CASE2.put(YourActualEnum.STATUS_TWO, "twoTwo");
        CASE3 = new EnumMap<>(YourActualEnum.class);
        CASE3.put(YourActualEnum.STATUS_ONE, "oneThree");
        CASE3.put(YourActualEnum.STATUS_TWO, "twoThree");
    }
    public void foo(boolean one, boolean two, boolean three, YourActualEnum status) {
        if (one) {
            caseOne(status, CASE1);
        }

        if (two) {
            caseTwo(status, CASE2);
        }

        if (three) {
            caseThree(status, CASE3);
        }
    }

    private void caseOne(YourActualEnum status, EnumMap<YourActualEnum,String> m) {
        m.get(status);
    }

    private void caseTwo(YourActualEnum status, EnumMap<YourActualEnum,String> m) {
        m.get(status);
    }

    private void caseThree(YourActualEnum status, EnumMap<YourActualEnum,String> m) {
        m.get(status);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM