使用 Singleton 对象作为枚举元素的 Scala 枚举以及迭代它们的可能性?

发布于 2024-10-03 17:33:39 字数 2159 浏览 4 评论 0原文

我已经看过关于模拟Java的Scala问题enum案例类与枚举 但似乎付出太多努力却收效甚微。

基本上我希望有一个 values 方法返回 DayOfWeek 的所有单例对象,而无需重复几次。

我的代码应该是这样的:

object DayOfWeek extends MyEnum {
  object MONDAY extends DayOfWeek(1)
  object TUESDAY extends DayOfWeek(2)
  object WEDNESDAY extends DayOfWeek(3)
  object THURSDAY extends DayOfWeek(4)
  object FRIDAY extends DayOfWeek(5)
  object SATURDAY extends DayOfWeek(6)
  object SUNDAY extends DayOfWeek(7)
}

class DayOfWeek(ordinal: Int)

方法 values 应该返回类似于这样编写的内容:

val values = Array(MONDAY, TUESDAY, WEDNESDAY, THURSDAY,
                   FRIDAY, SATURDAY, SUNDAY)

一切都应该发生在 MyEnum 特征中,所以我只需要扩展它以获得功能。

trait MyEnum {
  val values = this.getClass.getField("MODULE$") etc. etc.
}

有什么建议可以准确地做到这一点吗? 这个想法是 values 访问类并查找它们正在扩展的类的所有单例对象。

编辑:看起来所有建议都没有考虑到用户也可以创建对象,这些对象当然应该与定义的对象相当。

我会尝试举另一个例子,也许是更清楚:

object MonthDay extends MyEnum {
  //Some important holidays
  object NewYear       extends MonthDay( 1,  1)
  object UnityDay      extends MonthDay(11,  9)
  object SaintNicholas extends MonthDay(12,  6)
  object Christmas     extends MonthDay(12, 24)
}

class MonthDay(month: Int, day: Int)

//Of course the user can create other MonthDays
val myBirthDay = new MonthDay(month, day)

if(!MonthDay.values.contains(myBirthDay)) "Well, I probably have to work"
else "Great, it is a holiday!"

我想要一个特征(MyEnum),我可以将其混合到保存我的“枚举对象”的对象中,并使用方法返回它们的列表(def 值:List[MonthDay ])或迭代它们(def next: MonthDaydef previous: MonthDay)。

PPS:我按照 Ken Bloom 的要求为此问题的第二部分创建了一个新问题

I already looked at the Scala question about emulating Java's enum and case classes vs. Enumeration but It seems too much effort for too less benefit.

Basically I would like to have a values method returning all singleton objects of DayOfWeek without repeating myself a few times.

This is how my code should look like:

object DayOfWeek extends MyEnum {
  object MONDAY extends DayOfWeek(1)
  object TUESDAY extends DayOfWeek(2)
  object WEDNESDAY extends DayOfWeek(3)
  object THURSDAY extends DayOfWeek(4)
  object FRIDAY extends DayOfWeek(5)
  object SATURDAY extends DayOfWeek(6)
  object SUNDAY extends DayOfWeek(7)
}

class DayOfWeek(ordinal: Int)

The method values should return something like if it had been written like this:

val values = Array(MONDAY, TUESDAY, WEDNESDAY, THURSDAY,
                   FRIDAY, SATURDAY, SUNDAY)

Everything should happen in the MyEnum trait so I only need to extend it to get the functionality.

trait MyEnum {
  val values = this.getClass.getField("MODULE$") etc. etc.
}

Any suggestion how this could be done exactly?
The idea is that values accesses the class and finds all singleton objects of the class they are extending.

Edit: It looks like all suggestions don't take in account that the user can create objects too which should of course be comparable to the defined ones.

I'll try to give another example, maybe it is more clear:

object MonthDay extends MyEnum {
  //Some important holidays
  object NewYear       extends MonthDay( 1,  1)
  object UnityDay      extends MonthDay(11,  9)
  object SaintNicholas extends MonthDay(12,  6)
  object Christmas     extends MonthDay(12, 24)
}

class MonthDay(month: Int, day: Int)

//Of course the user can create other MonthDays
val myBirthDay = new MonthDay(month, day)

if(!MonthDay.values.contains(myBirthDay)) "Well, I probably have to work"
else "Great, it is a holiday!"

I want to have a trait (MyEnum) which I can mix into the object holding my "enumeration objects" with methods to return a list of them (def values: List[MonthDay]) or iterate over them (def next: MonthDay or def previous: MonthDay).

PPS: I created a new question for the second part of this question as requested by Ken Bloom.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

潜移默化 2024-10-10 17:33:39

这个怎么样?它要求您为每个新值实际调用 add 方法,但 values 返回正确的类型。

abstract class MyEnum{

   type Value     //define me to be the value type for this MyEnum

   private var _values:List[Value] = Nil
   def values = _values    
   protected def add(newValue:Value) = {
      _values = newValue::_values
      newValue
   }
}

object DayOfWeek extends MyEnum{
   class Value(val dayNum:Int)
   val SUNDAY    = add(new Value(1))
   val MONDAY    = add(new Value(2))
   val TUESDAY   = add(new Value(3))
   val WEDNESDAY = add(new Value(4))
   val THURSDAY  = add(new Value(5))
   val FRIDAY    = add(new Value(6))
   val SATURDAY  = add(new Value(7))
}

您现在可以调用

println(DayOfWeek.values map (_.dayNum))

如果您需要在不同对象上具有不同方法定义的单例对象,则可以创建匿名类,如下所示:

add(new Value{
      override def dayNum=8
    })

How about this? It requires you to actually call an add method for each new value, but values returns the right type.

abstract class MyEnum{

   type Value     //define me to be the value type for this MyEnum

   private var _values:List[Value] = Nil
   def values = _values    
   protected def add(newValue:Value) = {
      _values = newValue::_values
      newValue
   }
}

object DayOfWeek extends MyEnum{
   class Value(val dayNum:Int)
   val SUNDAY    = add(new Value(1))
   val MONDAY    = add(new Value(2))
   val TUESDAY   = add(new Value(3))
   val WEDNESDAY = add(new Value(4))
   val THURSDAY  = add(new Value(5))
   val FRIDAY    = add(new Value(6))
   val SATURDAY  = add(new Value(7))
}

You can now call

println(DayOfWeek.values map (_.dayNum))

If you need singleton objects that have different definitions of the methods on different objects, you can create anonymous classes like so:

add(new Value{
      override def dayNum=8
    })
心安伴我暖 2024-10-10 17:33:39

scala.Enumeration 已经完全满足您的要求了。

我认为您可能对 Scala 2.7 和 Scala 2.8 感到困惑。您引用的关于模拟Java的enum 是在 Scala 2.7 时代编写的,虽然我无法测试 Scala 2.7 的 Enumeration 拥有什么功能,但 Scala 2.8 的 枚举肯定拥有您正在寻找的一切。

您无法使用 object SUNDAY extends Value(1) 定义值,因为 object 是延迟初始化的。

scala.Enumeration does exactly what you want already.

I think you may be confused by Scala 2.7 versus Scala 2.8. The old question you cite about emulating Java's enum was written in the days of Scala 2.7, and though I can't go test what functionality Scala 2.7's Enumerations posessed, Scala 2.8's Enumerations certainly possess everything you're looking for.

You can't define values with object SUNDAY extends Value(1) because objects are initialized lazily.

ˇ宁静的妩媚 2024-10-10 17:33:39

我能想到的最接近的是:

abstract class MyEnum(val displayName:String){
   protected object Value{
      var _values:List[Value] = Nil
      def values = _values
   }
   protected class Value (val value:Int){
      Value._values = this::Value._values
      override def toString = "%s(%d)".format(displayName,value)
   }
   def values = Value.values
}

trait Methods{
   def dayName
}

object DayOfWeek extends MyEnum("DayOfWeek"){
   val SUNDAY = new Value(1) with Methods{
      override def dayName = "Sunday"
   }
   val MONDAY = new Value(2) with Methods{
      override def dayName = "Monday"
   }
   val TUESDAY = new Value(3) with Methods{
      override def dayName = "Tuesday"
   }
   val WEDNESDAY = new Value(4) with Methods{
      override def dayName = "Wednesday"
   }
   val THURSDAY = new Value(5) with Methods{
      override def dayName = "Thursday"
   }
   val FRIDAY = new Value(6) with Methods{
      override def dayName = "Friday"
   }
   val SATURDAY = new Value(7) with Methods{
      override def dayName = "Saturday"
   }
}

我还没有弄清楚如何更改 _values 变量的类型以捕获完整类型 Value withMethods

The closest I've been able to come up with is:

abstract class MyEnum(val displayName:String){
   protected object Value{
      var _values:List[Value] = Nil
      def values = _values
   }
   protected class Value (val value:Int){
      Value._values = this::Value._values
      override def toString = "%s(%d)".format(displayName,value)
   }
   def values = Value.values
}

trait Methods{
   def dayName
}

object DayOfWeek extends MyEnum("DayOfWeek"){
   val SUNDAY = new Value(1) with Methods{
      override def dayName = "Sunday"
   }
   val MONDAY = new Value(2) with Methods{
      override def dayName = "Monday"
   }
   val TUESDAY = new Value(3) with Methods{
      override def dayName = "Tuesday"
   }
   val WEDNESDAY = new Value(4) with Methods{
      override def dayName = "Wednesday"
   }
   val THURSDAY = new Value(5) with Methods{
      override def dayName = "Thursday"
   }
   val FRIDAY = new Value(6) with Methods{
      override def dayName = "Friday"
   }
   val SATURDAY = new Value(7) with Methods{
      override def dayName = "Saturday"
   }
}

I haven't figured out how to change the type of the _values variable to capture the full type Value with Methods.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文