如何在Scala中向Enumeration添加方法?

Eta*_*tam 38 java enums enumeration scala

在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();
}
Run Code Online (Sandbox Code Playgroud)

你是如何在Scala中做到这一点的?

编辑/有用的链接:

小智 36

以下是通过扩展Enumeration.Val类向scala枚举添加属性的示例.

object Planet extends Enumeration { 
   protected case class Val(val mass: Double, val radius: Double) extends super.Val { 
     def surfaceGravity: Double = Planet.G * mass / (radius * radius) 
     def surfaceWeight(otherMass: Double): Double = otherMass * surfaceGravity 
   } 
   implicit def valueToPlanetVal(x: Value) = x.asInstanceOf[Val] 

   val G: Double = 6.67300E-11 
   val Mercury = Val(3.303e+23, 2.4397e6) 
   val Venus   = Val(4.869e+24, 6.0518e6) 
   val Earth   = Val(5.976e+24, 6.37814e6) 
   val Mars    = Val(6.421e+23, 3.3972e6) 
   val Jupiter = Val(1.9e+27, 7.1492e7) 
   val Saturn  = Val(5.688e+26, 6.0268e7) 
   val Uranus  = Val(8.686e+25, 2.5559e7) 
   val Neptune = Val(1.024e+26, 2.4746e7) 
} 

scala> Planet.values.filter(_.radius > 7.0e6) 
res16: Planet.ValueSet = Planet.ValueSet(Jupiter, Saturn, Uranus, Neptune) 
Run Code Online (Sandbox Code Playgroud)

  • 您也可以使用`super.Val`进行扩展而不使用`nextId`和`name`参数.像这样:`protected case class Val(val mass:Double,val radius:Double)扩展super.Val`.这样你就可以创建没有值名称的值,如下所示:`val Mercury = Val(3.303e + 23,2.4397e6)` (3认同)

Aar*_*rup 33

基于Chris的解决方案,您可以通过隐式转换实现更好的语法:

object Suit extends Enumeration {
   val Clubs, Diamonds, Hearts, Spades = Value

   class SuitValue(suit: Value) {
      def isRed = !isBlack
      def isBlack = suit match {
         case Clubs | Spades => true
         case _              => false
      }
   }

   implicit def value2SuitValue(suit: Value) = new SuitValue(suit)
} 
Run Code Online (Sandbox Code Playgroud)

然后你可以打电话,例如Suit.Clubs.isRed.

  • 现在你甚至可以使用隐式类而不是类+隐式def:隐式类SuitValue(...){...} (8认同)

soc*_*soc 12

Scala 枚举与Java枚举不同.

目前,没有办法添加方法(以理智的方式).有一些解决方法,但没有任何东西适用于所有情况,看起来不像句法垃圾.

我尝试了类似的东西(为枚举的类实例添加方法,同时能够在运行时创建新实例,并在objects和new类的实例之间具有工作等效关系),但是被错误#4023("getClasses" 停止了/ getDeclaredClasses似乎错过了一些(REPL)或所有(scalac)类(对象)声明的").

我看看这些相关问题:

老实说,我不会用Enumeration.这是一个源自Scala 1.0(2004)的类,它有很奇怪的东西,并没有很多人(除了那些编写它的人)在没有教程的情况下理解如何使用它.

如果我绝对需要枚举,我会用Java编写该类.

  • +1,是的枚举目前有点奇怪. (3认同)

mis*_*tor 11

如果你不需要迭代枚举值或做一些其他的枚举,我建议使用ADT而不是Enumeration.

sealed abstract class Enum {
  def method: String = this match {
    case One => "1"
    case Two => "2"
    case Three => "3"
  }
}
case object One extends Enum
case object Two extends Enum
case object Three extends Enum
Run Code Online (Sandbox Code Playgroud)

这种方法有一个优点,Enumeration即当您忘记match表达式中的一个或多个案例时,编译器会发出警告.

  • ADT代表什么? (2认同)

oze*_*bee 8

详细阐述了Aaron的解决方案,Scala 2.10中使用隐式类的更紧凑的形式:

object Suit extends Enumeration {
   val Clubs, Diamonds, Hearts, Spades = Value

   implicit class SuitValue(suit: Value) {
      def isRed = !isBlack
      def isBlack = suit match {
         case Clubs | Spades => true
         case _              => false
      }
   }
} 
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它: Suit.Clubs.isRed


oxb*_*kes 7

你可以这样做:

object Suit extends Enumeration {
  val Clubs, Diamonds, Hearts, Spades = Value

  def isRed(suit : Value) = !isBlack(suit)
  def isBlack(suit : Value) = suit match {
    case Clubs | Spades => true
    case _              => false
  }
}
Run Code Online (Sandbox Code Playgroud)

显然这不完美,但你可以这样做:

Suit.isBlack(Suit.Clubs)
Run Code Online (Sandbox Code Playgroud)

  • 太好了!考虑到当前的限制,将静态辅助方法添加到周围的类看起来就像是最佳方法. (2认同)

Eta*_*tam 4

object Unit extends Enumeration {
  abstract class UnitValue(var name: String) extends Val(name) {
    def m: Unit
  }
  val G = new UnitValue("g") {
    def m {
        println("M from G")
    }
  }
  val KG = new UnitValue("kg") {
    def m {
        println("M from KG")
    }
  }
}
Run Code Online (Sandbox Code Playgroud)