你怎么能在Scala中用访问者语义编写一个强大的Enum?

Rob*_*Jr. -1 enumeration scala visitor-pattern

我经常使用一种模式来使代码更简单,我喜欢称之为Power Enum,它是一个利用访问者模式以及携带自定义数据的枚举.这是Java中的一个例子:

import java.security.SecureRandom;
import java.util.UUID;
import java.util.stream.IntStream;

public class PowerEnumDemo {
    private static final SecureRandom random = new SecureRandom();

    public static void main(String[] args) {
        for (int i = 0; i < 3 ; i++) {
            final Color selected = Color.values()[random.nextInt(3)];
            System.out.println("Selected: " + selected);
            System.out.println("rgb: " + selected.rgb);
            selected.visit();
        }
    }

    public enum Color {
        RED("0000ff") {
            @Override
            public void visit() {
                IntStream.range(1, 10).forEach(System.out::println);
            }
        },
        GREEN("00ff00") {
            @Override
            public void visit() {
                System.out.println(UUID.randomUUID().toString().chars().filter(c -> c == 'a').count());
                ;
            }
        },
        BLUE("ff0000") {
            @Override
            public void visit() {
                System.out.println("Hello World");
            }
        };
        final String rgb;

        Color(final String rgb) {
            this.rgb = rgb;
        }

        /**
         * This is where the enum implements the visitor pattern to do special stuff.
         */
        public abstract void visit();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果运行这个小程序,你会看到它是如何工作的.我们不必知道选择了哪个枚举,如果循环可能令人烦恼,我们不必做任何维护.如果开发人员添加了新的枚举,他们必须定义其数据并实现访问方法或代码不会编译.但是当他们这样做时,它将适用于所有呼叫访问的人.

我想在Scala中实现它,但我不知道如何继续.以下是创建枚举的禁止方法,它有点模糊:

object Color extends Enumeration{
  type Color = Value
  val RED, GREEN, BLUE = Value
}
Run Code Online (Sandbox Code Playgroud)

我没有看到的是如何定义我的自定义数据和我的抽象访问方法,并让每个val实现访问方法.(对于那些在java示例中没有得到它的人来说,每个枚举都是主要颜色枚举的子类型.)那么你们中的任何一个scala大师都可以使用它吗?:-)

Jas*_*r-M 5

对于Scala中的枚举,我会使用密封特征而不是Enumeration类.特别是对于这样的用例.

sealed trait Color {
  def visit: Unit
  def rgb: String
}
object Color {
  case object RED extends Color {
    def visit = println("Hello World!")
    val rgb = "ff0000"
  }
  ....
}
Run Code Online (Sandbox Code Playgroud)