Scala Lazy Val Вопрос - PullRequest
       9

Scala Lazy Val Вопрос

1 голос
/ 19 января 2011

У меня есть сценарий, в котором у меня есть некоторые объекты, которые должны брать ссылки друг от друга. Единственный способ получить это для компиляции - использовать lazy

class A(b:B)
class B(a:A)
lazy val a:A = new A(b)
lazy val b:B = new B(a)

Я могу сделать то же самое, используя некоторые актеры, и заставить его также скомпилировать

    abstract class Message
    case class Message1 extends Message
    case class Message2 extends Message

    class Actor1(otherActor:Actor) extends Actor {
        def act() {
            loop {
                react {
                    case Message1 =>
                        println("received message1")
                        otherActor ! Message2
                    case _ =>
                }
            }
        }
    }

    class Actor2(otherActor:Actor) extends Actor {
        def act() {
            loop {
                react {
                    case Message2 =>
                        println("received message2")
                        otherActor ! Message1
                    case _ =>
                }
            }
        }
    }

    lazy val actor1:Actor = new Actor1(actor2)
    lazy val actor2:Actor = new Actor2(actor1)

Однако, когда я добавляю следующее:

    actor1.start
    actor2.start
    actor1 ! Message1

Я получаю следующую ошибку:

Исключение в теме "главная" java.lang.NoClassDefFoundError: ком / fictitiousCompany / stackOverflowQuestion / Test Вызванный: java.lang.ClassNotFoundException: com.fictitiousCompany.stackOverflowQuestion.Test в java.net.URLClassLoader $ 1.run (URLClassLoader.java:202) в java.security.AccessController.doPrivileged (Native Метод) в java.net.URLClassLoader.findClass (URLClassLoader.java:190) в java.lang.ClassLoader.loadClass (ClassLoader.java:307) в sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:301) в java.lang.ClassLoader.loadClass (ClassLoader.java:248)

Я использую плагин Scala Eclipse 2.8.1.

1 Ответ

11 голосов
/ 19 января 2011

Обратите внимание, что даже у вашего меньшего примера будут проблемы (в REPL):

{
class A(b:B)
class B(a:A)
lazy val a:A = new A(b)
lazy val b:B = new B(a)
a
}
// causes stack overflow error

Как только необходимо вычислить оценку a, для нее потребуется B, что требует A. ВДля того, чтобы это работало, a или b должно быть закончено.

Использование параметров по имени позволяет оценить меньший пример.

{
class A(b: => B)
class B(a: => A)
lazy val a:A = new A(b)
lazy val b:B = new B(a)
a
}

Обратите внимание, что еслиЯ тоже буду работать на примере вашего актера.

Редактировать: по имени параметры работали локально на 2.8.0.Я заменил класс case на object, чтобы избавиться от некоторых предупреждений об устаревании, и добавил методы start для actor1, actor2 и ударил все это с помощью actor1 ! Message1.Кроме того, я не использовал актера раньше, поэтому я не могу комментировать больше.Вот что я проверил:

import scala.actors._

abstract class Message
object Message1 extends Message
object Message2 extends Message

class Actor1(otherActor: => Actor) extends Actor {
def act() {
    loop {
    react {
        case Message1 =>
        println("received message1")
        otherActor ! Message2
        case _ =>
    }
    }
}
}

class Actor2(otherActor: => Actor) extends Actor {
def act() {
    loop {
    react {
        case Message2 =>
        println("received message2")
        otherActor ! Message1
        case _ =>
    }
    }
}
}

{
  lazy val actor1:Actor = new Actor1(actor2)
  lazy val actor2:Actor = new Actor2(actor1)
  actor1.start
  actor2.start
  actor1 ! Message1
}

Печатает кучу:

received message1
received message2
...