2017-04-01 19 views
-1

コードをシンプルにするために頻繁に使用するパターンがあります。これは、訪問者パターンを利用してカスタムデータを保持する列挙型のPower Enumを呼び出すのが好きです。 Javaの例を次に示します。Scalaでビジターセマンティクスを使用してPower Enumを作成するにはどうすればよいですか?

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

この小さなプログラムを実行すると、その動作方法がわかります。どのEnumが選択されているかを知る必要はなく、ループを維持するのが面倒なifループを行う必要はありません。開発者が新しい列挙型を追加する場合、データを定義して訪問メソッドを実装するか、コードをコンパイルしないでください。しかし、彼らがそうするとき、訪問するすべての人のために働くでしょう。

私はこれをScalaで実装したいと思いますが、私はどのように処理するのか迷っています。ここでは少しあいまいである列挙型を作成するための禁止された方法は次のとおりです。

object Color extends Enumeration{ 
    type Color = Value 
    val RED, GREEN, BLUE = Value 
} 

私は表示されませんどのようなことは、私は私のカスタムデータと私の抽象訪問メソッドを定義し、各valが訪問メソッドを実装持つことができる方法です。 (Javaの例でそれを取得しない人は、各列挙型は主なColor列挙型のサブタイプのようなものです。)だから、あなたのスケーラ達の誰もがこれを得ることができますか? :-)

+1

いくつかの選択肢。それが助けてくれることを願う – pedrorijo91

+0

もしそれが起これば、それは素晴らしいだろう。私はちょうどその問題についてコメントしました。その間に何をすべきかを知ることは、素晴らしいことです。 –

+1

訪問者パターンに関連するものは何もありません。それはメソッドオーバーライドによる特定の振る舞い定義を持つ単なるランク・オブ・ザ・ミルのサブクラス化です。あなたはバニラ封印された形質に固執するか、enumeratum(https://github.com/lloydmeta/enumeratum)を使用することができます。また、訪問者のパターンを参照しないように質問を編集/改訂することは可能でしょうか?これにより、回答者と同様のものを検索する人々の間の混乱が大幅に軽減されます。 – tkroman

答えて

5

Scalaの列挙型の場合は、Enumerationクラスの代わりに密閉された特性を使用します。特にこのような使用例の場合。 http://pedrorijo.com/blog/scala-enums/とhttp://pedrorijo.com/blog/scala-enums-part2/で説明したScalaの列挙に

sealed trait Color { 
    def visit: Unit 
    def rgb: String 
} 
object Color { 
    case object RED extends Color { 
    def visit = println("Hello World!") 
    val rgb = "ff0000" 
    } 
    .... 
} 
+0

これは私がやったことですが、より良い方法があるかどうかを知りたがっています。明らかに、これはColor.values()と言うような列挙の面の多くを欠いています。 –

関連する問題