我可以在Java的Enum中使用类似Swift的函数类型吗?

时间:2016-09-01 09:32:24

标签: java swift oop enums

是否可以在Java中为以下swift代码编写等效代码?事实上,我想知道在Java的枚举中是否可以有一个函数的例子(MyEnum中的X,Y)

enum MyEnum{
    case X((Int) -> String)
    case Y((Double) -> Int)
}

3 个答案:

答案 0 :(得分:3)

不,你不能;至少,如果您希望在使用枚举时可以使用不同的类型。所有枚举值必须具有相同的类型。

如果希望“枚举”值具有异类型,则可以使用具有静态最终字段的类:

final class MyHeterogeneousEnum {
  private MyHeterogeneousEnum() {}  // Not instantiable.

  static final Function<Integer, String> X = ...;
  static final Function<Double, Integer> Y = ...;
}

允许您将值与其完整类型信息一起使用:

String s = MyHeterogeneousEnum.X.apply(123);
Integer i = MyHeterogeneousEnum.Y.apply(999.0);

当然,您没有像name()values()这样的有用方法来迭代这个类中的常量,也不具有内在的可序列化。您可以自己实现这些 - 但对于values(),您必须在返回类型中使用通配符,以便可以返回所有值:

static Iterable<Function<?, ?>> values() {
  return Collections.unmodifiableList(Arrays.asList(X, Y));
}

但是,请注意带有通配符输入类型参数的Function几乎没用:您实际上无法将任何内容传递给它(null除外);所以values()方法的效用有限。

答案 1 :(得分:2)

有可能(技术上),但它可能没有那么有用,因为创建一个消耗Function实例的简单类。

您可能已经知道,在Java中,枚举表示一个或多个相同类型的常量,这些常量可以有自己的属性 - 这包括java.util.Function个实例。但是,这些Function实例不能在运行时动态传递,而应在编译时设置,以便创建常量。

当然,您可以通过创建枚举的构造函数Generic来使每个枚举常量具有不同的类型Function

enum MyEnum {
    X((String x) -> "Hello"), Y((Double d) -> 1);

    Function<?, ?> function;

    MyEnum(Function<?, ?> function) {
        this.function = function;    
    }
}

然而,这并不是很有用(尽管编译得很好)。 Function中的X不使用它的String参数并返回固定值。 Y中的那个也是如此。

我宁愿介绍同一个类的两个独立实例:

class Instance<T, U> {

    private Function<T, U> function;

    public Instance(Function<T, U> function) {
         this.function = function;
    }
}

这将允许您动态传递Function实例,而不是在编译时设置它。

答案 2 :(得分:1)

是的,你肯定可以,在java枚举中可以更多只是常量...它的每一个值都可以是一个匿名类(例如看看TimeUnit.class)

现在,你可以这样做:

interface IFunction {
    double getY(double x);
}


enum Function implements IFunction {
    LINE {
    @Override
    public double getY(double x) {
        return x;
    }
    },
    SINE {
    @Override
    public double getY(double x) {
        return Math.sin(x);
    }
    }
}

然后执行

public static void main(String[] args) {
    for (int i = 0; i < 100; i++) {
        System.out.println(Function.LINE.getY(i));
        System.out.println(Function.SINE.getY(i));
    }
}