answer, which tells that Scala enums do not support args/methods-customized values 似乎是错误的。其他答案(其中一些涉及implicit)表明它可以做到,但它们会产生需要名称重复的印象:您的值已将名称声明为java对象字段,其次,名称作为字符串提供给值构造函数,而Enums 的重点是创建一个可迭代的名称-> 值映射,而 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
其他用户争论密封特征+宏的情况,Iteration over a sealed trait in Scala?