我可以获得 Java 类 的可变数量的泛型类型,甚至是一般的泛型类型吗?

Can I get a variable number of generic types for Java classes, or even in general?

我想伪造一个名为 "EnumTuple" 的通用数据 class,它将来自不同枚举 class 的自然数的不同枚举元素一起存储在一个元组中。 假设我得到了那三个 Enum classes:

public Enum Gender {
    FEMALE, MALE, OTHER
}

public enum Age {
    YOUNG, MIDDLEAGED, OLD
}

public enum Personality {
    EXTROVERT, INTROVERT
}

我希望能够像这样实例化 EnumTuple class:

EnumTuple person1 = new EnumTuple<Gender, Age, Personality>(Gender.OTHER, Age.MIDDLEAGED, Personality.EXTROVERT);
EnumTuple person2 = new EnumTuple<Personality, Gender>(Personality.INTROVERT, Gender.FEMALE);
EnumTuple person3 = new EnumTuple<Age>(Age.OLD);

但我不知道如何到达那里,或者是否有可能在 Java 或 Kotlin 中写入这样的数据 class 开始,因为它看起来每个 class 只能有固定数量的泛型。

对于那些好奇的人,我正在尝试实现候选消除算法 (https://artint.info/html/ArtInt_193.html) 的干净通用版本,其中输入特征集是我尝试的枚举元素元组设计.

最后,如果您手头有适合我的解决方法或知道另一种支持可变数量泛型类型的编程语言,请告诉我

你不能在 Java 或 Kotlin 中这样做,因为正如你想象的那样,每个 class 只能有固定数量的泛型。

您可以在此处执行的唯一解决方法是,无需事先手动指定所有组合,即在每次使用枚举时检查枚举的实例,创建 EnumTuplevararg Enum<*>

例如(在 Kotlin 中)

class EnumTuple(vararg enums: Enum<*>)

[...] or know another programming language that supports a variable number of generic types, please let me know.

使用可变参数模板的 C++ 支持此功能。 https://en.cppreference.com/w/cpp/language/parameter_pack

根据用例,EnumTuple 将使用它具有的每个功能进行比较。而且特征的数量是灵活的,我会建议如下设计。

  1. 添加一个枚举 FeatureType,它将包含所有可能的特征。
  2. 添加一个接口Feature,每个功能枚举都会实现这个接口。
  3. EnumTuple中,我们将使用一个Map<FeatureType, Feature>来存储特征。

public enum FeatureType {
    AGE, GENDER, PERSONALITY;
}

public enum Age implements Feature {
    YOUNG, MIDDLEAGED, OLD;

    @Override
    public FeatureType getFeatureType() {
        return FeatureType.AGE;
    }
}

public enum Personality implements Feature {
    EXTROVERT, INTROVERT;

    @Override
    public FeatureType getFeatureType() {
        return FeatureType.PERSONALITY;
    }
}

public enum Gender implements Feature {
    FEMALE, MALE, OTHER;

    @Override
    public FeatureType getFeatureType() {
        return FeatureType.GENDER;
    }
}

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Assert;

public class EnumTuple {
    private Map<FeatureType, Feature> featureTypeToFeatureMap = new HashMap<>();

    public EnumTuple(List<Feature> features) {
        for (Feature feature : features) {
            featureTypeToFeatureMap.put(feature.getFeatureType(), feature);
        }
    }

    public boolean hasFeature(FeatureType featureType) {
        return featureTypeToFeatureMap.containsKey(featureType);
    }

    public Feature getFeature(FeatureType featureType) {
        return featureTypeToFeatureMap.get(featureType);
    }

    public Map<FeatureType, Boolean> getDifferenceTo(EnumTuple enumTuple) {
        if (!this.featureTypeToFeatureMap.keySet().equals(enumTuple.featureTypeToFeatureMap.keySet())) {
            throw new IllegalArgumentException("Contains different featureTypes");
        }
        Map<FeatureType, Boolean> difference = new HashMap<>();
        for (FeatureType featureType : this.featureTypeToFeatureMap.keySet()) {
            difference.put(featureType, this.getFeature(featureType).equals(enumTuple.getFeature(featureType)));
        }
        return difference;
    }

    public boolean isEqualsTo(EnumTuple other) {
        if (featureTypeToFeatureMap == null) {
            if (other.featureTypeToFeatureMap != null)
                return false;
        } else if (!featureTypeToFeatureMap.equals(other.featureTypeToFeatureMap))
            return false;
        return true;
    }

    public static void main(String[] args) {
        EnumTuple person1 = new EnumTuple(Arrays.asList(Gender.OTHER, Age.MIDDLEAGED, Personality.EXTROVERT));
        EnumTuple person2 = new EnumTuple(Arrays.asList(Gender.OTHER, Age.MIDDLEAGED, Personality.EXTROVERT));
        EnumTuple person3 = new EnumTuple(Arrays.asList(Gender.FEMALE, Age.MIDDLEAGED, Personality.EXTROVERT));
        Assert.assertTrue(person1.isEqualsTo(person2));
        Assert.assertFalse(person1.isEqualsTo(person3));
        Assert.assertEquals(person1.getDifferenceTo(person2).toString(), "{PERSONALITY=true, GENDER=true, AGE=true}");
        Assert.assertEquals(person1.getDifferenceTo(person3).toString(), "{PERSONALITY=true, GENDER=false, AGE=true}");
    }
}