1

我有以下描述枚举的代码:

package aicore2.worker.scheduling
    object Priority extends Enumeration with App {
      type Priority = Value

      /**
       * Action is performed immediately, any running action is interrupted
       * and action queue is cleared
       */
      val ACHTUNG = Value

      /**
       * Action is performed before all LOW, NORMAL and HIGHER actions
       */
      val HIGH = Value

      /**
       * Action is performed before all NORMAL and LOW actions
       */
      val HIGHER = Value

      /**
       * Standart priority for most actions
       */
      val NORMAL = Value

      /**
       * Action is added to the end of the queue. Desired for non-critical maintenance actions
       */
      val LOW= Value


      Priority.values  foreach println
    }

和一个测试:

package aicore2.worker.scheduling

import org.junit.Assert._
import org.junit.Test
import aicore2.worker.scheduling.Priority._

class PriorityTypeTests {

  @Test
  def toStringTest()  {
    //Priority.values  foreach println
    //Priority.main(Array("2"))
    assertEquals(HIGH.toString(), "HIGH")
  }

  @Test
  def stringParseTest() {
     assertEquals(Priority.withName("HIGH"), HIGH)
  }

}

当我运行测试时,我得到 NPE (HIGH=null)。

当我将 Priority 作为 App 运行时,我会得到我想要的任何东西: ACHTUNG HIGH HIGH NORMAL LOW

在运行测试之前调用 Priority.main() 时得到相同的结果并且没有 NPE。当我从 Priority 标头(“with App”)中删除 App trait mix-in 时,所有测试都按预期通过。我知道当我混合 App 特征时,初始化顺序有些奇怪,但我是 Scala 的新手(来自 Java 领域的难民),还没有足够的经验来解决问题。

4

2 回答 2

2

Appmain意味着在您运行该方法之前成员不会被初始化。在 REPL 中尝试以下操作:

object A { val x = "foo" }
object B extends App { val x = "foo" }
A.x // = "foo"
B.x // = null

在您使用 App 的 Enumeration 类中,所有成员都null在您调用它的main方法之前。所以HIGH.toString()从你的测试方法中会导致一个 nullPointerException 因为HIGH没有被初始化。

Enumeration因此,赋予特征似乎是一个非常糟糕的主意App

于 2012-06-18T17:37:23.633 回答
1

Apptrait 扩展了trait,延迟了其成员的DelayedInit初始化,直到它被显式请求(在Apptrait 的应用程序开始时)。您应该将其视为主要方法制作的对象。

有关AppandDelayedInit特征的更多信息,您可以阅读Scala 2.9.0 发行说明

于 2012-06-18T15:21:38.363 回答