簡體   English   中英

在子類上下文中使用帶有枚舉鍵類型的 Map 的泛型類型

[英]Using generic types with a Map typed with Enum keys in a subclass context

我有以下結構,父 class,幾個子類,每個子類都有自己的 Enum 和各種鍵。 父 class 需要有一個 map 具有以 Enum 為特征的鍵,但 Enum 類型是抽象的 - 它由正在實例化的子類確定。

我想使用泛型類型來要求 Enum 類型來自特定的 class - 因此您只能將 APPLE 添加到 Fruits 並將 CELERY 添加到 Veggies ,反之亦然。 我的應用程序還要求任何 Food object 能夠查詢其可能的類型(例如,打印出所有可能的類型,而不僅僅是我們在地圖中的類型)。

我怎樣才能使用泛型類型來使這一切正常工作? 我在 EnumSet 聲明Uncompilable source code - type argument E is not within bounds of type-variable E

import java.util.*;

public class sandbox {

    private static class Food<E extends Enum> {

        public Map<E, Integer> qty = new HashMap<>();
        public EnumSet<E> types = EnumSet.allOf(E);

    }

    private static class Fruit extends Food<Fruit.Type> {

        public static enum Type {
            APPLE,
            ORANGE
        }

    }

    private static class Veggie extends Food<Veggie.Type> {

        public static enum Type {
            CUCUMBER,
            CELERY
        }
    }

    public static void main(String[] args) throws Exception {
        Fruit mondays = new Fruit();
        mondays.qty.put(Fruit.Type.APPLE, 1);
        mondays.qty.put(Fruit.Type.ORANGE, 3);

        Veggie tuesdays = new Veggie();
        tuesdays.qty.put(Veggie.Type.CELERY, 10);

        mondays.qty.forEach((f, qty) -> System.out.println("Buying " + f + " in qty " + qty));
        tuesdays.qty.forEach((f, qty) -> System.out.println("Buying " + f + " in qty " + qty));

        mondays.types.forEach(System.out::print);

    }
}

我會利用枚舉可以實現接口這一事實,使用接口作為Food的類型約束而不是Enum<> 然后將Food抽象化,以便每個特定的食物子類型都可以聲明其枚舉類型。

    private static interface FoodType {}

    private static abstract class Food<T extends FoodType> {

        public Map<T, Integer> qty = new HashMap<>();

        protected abstract Set<T> getTypes();

    }

    private static class Fruit extends Food<Fruit.Type> {

        public static enum Type implements FoodType {
            APPLE,
            ORANGE
        }

        @Override
        protected Set<Type> getTypes() {
            return EnumSet.allOf(Type.class);
        }

    }

    private static class Veggie extends Food<Veggie.Type> {

        public static enum Type implements FoodType {
            CUCUMBER,
            CELERY
        }

        @Override
        protected Set<Type> getTypes() {
            return EnumSet.allOf(Type.class);
        }
    }

如果您想要稍微DRY並避免在每個具體的Food子類中實現getTypes() ,您可以在受保護的構造函數中傳入枚舉值數組。 像這樣:

    private static interface FoodType { }

    private static abstract class Food<T extends FoodType> {
        public Map<T, Integer> qty;
        public Set<T> types;

        protected Food(T[] types) {
            this.types = Set.of(types);
            this.qty = new HashMap<>();
        }

    }

    private static class Fruit extends Food<Fruit.Type> {

        protected Fruit() {
            super(Type.values());
        }

        public static enum Type implements FoodType {
            APPLE,
            ORANGE;
        }
    }

    private static class Veggie extends Food<Veggie.Type> {

        protected Veggie() {
            super(Type.values());
        }

        public static enum Type implements FoodType {
            CUCUMBER,
            CELERY
        }
    }

暫無
暫無

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

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