Ответ , который сообщает, что перечисления 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?