【问题标题】:Can I get a variable number of generic types for Java classes, or even in general?我可以获得可变数量的 Java 类的泛型类型,甚至是一般类型吗?
【发布时间】:2020-05-01 09:20:04
【问题描述】:

我想伪造一个名为“EnumTuple”的通用数据类,它将来自不同 Enum 类的自然数量的不同 Enum 元素一起存储在一个元组中。 假设我得到了这三个 Enum 类:

public Enum Gender {
    FEMALE, MALE, OTHER
}

public enum Age {
    YOUNG, MIDDLEAGED, OLD
}

public enum Personality {
    EXTROVERT, INTROVERT
}

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

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 编写这样的数据类,因为看起来每个类只能有固定数量的泛型类型。

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

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

【问题讨论】:

  • 你会如何使用EnumTuple?您希望提供什么方法​​?
  • @samabcde 我打算逐个元素地比较两个相似泛型类型的 EnumTuples,以确定它们是否相等,以及它们在哪些元素上不同。让我们设置一些示例变量:EnumTuple&lt;Gender, Age&gt; person1 = EnumTuple&lt;Gender, Age&gt;(Gender.FEMALE, Age.YOUNG); EnumTuple&lt;Gender, Age&gt; person2 = EnumTuple&lt;Gender, Age&gt;(Gender.MALE, Age.YOUNG); 现在我希望能够比较它们:assertFalse(person1.isEqualTo(person2)); assertEquals(person1.getDifferenceTo(person2), [false, true]);
  • 我知道这也可以通过具有固定数量的泛型类型的普通泛型类来实现。我只是想让我的实现更加通用和可重用

标签: java generics kotlin tuples variadic


【解决方案1】:

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

您可以在此处执行的唯一解决方法是,无需事先手动指定所有组合,即每次使用枚举时检查它们的实例,并使用vararg Enum&lt;*&gt; 创建EnumTuple

例如(在 Kotlin 中)

class EnumTuple(vararg enums: Enum<*>)

[...] 或者知道另一种支持可变数量泛型类型的编程语言,请告诉我。

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

【讨论】:

    【解决方案2】:

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

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

    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}");
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-05
      • 1970-01-01
      相关资源
      最近更新 更多