Как добавить метод в перечисление в Scala? - PullRequest
37 голосов
/ 03 декабря 2010

В Java вы могли бы:

public enum Enum {
    ONE {
        public String method() {
            return "1";
        }
    },
    TWO {
        public String method() {
            return "2";
        }
    },
    THREE {
        public String method() {
            return "3";
        }
    };

    public abstract String method();
}

Как ты это делаешь в Scala?

РЕДАКТИРОВАТЬ / Полезные ссылки:

Ответы [ 11 ]

0 голосов
/ 19 июля 2014

Ответ , который сообщает, что перечисления Scala не поддерживают значения, настроенные для аргументов / методов , кажется неправильным. Другие ответы (некоторые из них включают implicit) демонстрируют, что это возможно, но создают впечатление, что требует дублирования имен: ваше значение объявлено как поле объекта java, а во-вторых, имя передается конструктору значения как строка, тогда как Весь смысл Enums состоит в том, чтобы создать итерируемую карту name-> value, и Scala может обойтись без избыточности:

object Ops1 extends Enumeration {

    protected case class OpsVal(f: Int => Int) extends super.Val(/*nextId*/)

    val ZERO = new FuncVal (x => 0)
    val DOUBLE = new FuncVal (x => 2 * x )

    implicit def convert(v: Value) = v.asInstanceOf[OpsVal]

}

// implicit is not needed
Ops1.ZERO.f(1)                            //> res0: Int = 0

// implicit is needed
Ops1.values map (v => (v + "=>" + v.f(1)))//> res1: scala.collection.immutable.SortedSet[String] = TreeSet(DOUBLE=>2, ZERO=>0)

Я думаю, что вышесказанное является более кратким, чем

object Ops2 extends Enumeration {

    protected abstract class OpsVal extends Val() {
      def f(a: Int): Int
    }

    val ZERO = new OpsVal { def f(x: Int) = 0 }
    val DOUBLE = new OpsVal { def f(x: Int) = 2 * x }

    implicit def convert(valu: Value) = valu.asInstanceOf[OpsVal]
}
Ops2.ZERO.f(1) // implicit is not needed  //> res2: Int = 0

// implicit is needed
Ops2_3.values map (v => (v, v(1)))        //> res7: scala.collection.immutable.SortedSet[(e.Ops2_3.Value, Int)] = TreeSet
                                              //| ((ZERO,0), (DOUBLE,2))

Поскольку для каждого значения существует один метод, мы можем преобразовать их в функции

object Ops2_3 extends Enumeration {

    protected case class FuncVal(f: Int => Int) extends Val {
        def apply(x: Int) = f(x) // no need to extend Function1 explicitly
    }

    val ZERO = new FuncVal (x => 0)
    val DOUBLE = new FuncVal (x => 2 * x )

    implicit def convert(v: Value) = v.asInstanceOf[FuncVal]

}
Ops2_3.ZERO(1) // implicit is not needed  //> res6: Int = 0

// implicit is needed
Ops2_3.values map (v => (v, v(1)))        //> res7: scala.collection.immutable.SortedSet[(e.Ops2_3.Value, Int)] = TreeSet
                                              //| ((ZERO,0), (DOUBLE,2))

Функции, общие для всех значений, могут быть определены следующим образом (используется в arg parser )

val args: Array[String] = "-silent -samples 100 -silent ".split(" +").toArray
                                              //> args  : Array[String] = Array(-silent, -samples, 100, -silent)
object Opts extends Enumeration {

    val nopar, silent, samples = new Val() {
        def apply() = args.contains(toString)
        def asInt(default: Int) = { val i = args.indexOf(toString) ;  if (i == -1) default else args(i+1).toInt}
        def asInt: Int = asInt(-1)
        override def toString = "-" + super.toString
    }
}

Opts.nopar()                              //> res0: Boolean = false
Opts.samples.asInt                        //> res1: Int = 100

Другие пользователи приводят доводы в пользу случаев запечатанных черт + макросов, Итерации по запечатанным чертам в Scala?

...