Сопутствующий объект в Scala не ассоциируется с классом case - PullRequest
3 голосов
/ 09 июня 2011

Мне трудно понять, почему этот код не работает. Я получил его из 99 Проблем Scala в разделе «Двоичные деревья» (http://aperiodic.net/phil/scala/s-99/). Для меня это действительно так: объект Node - это объект-компаньон для класса Node, и он добавляет конструктор для листьев на дереве. Но когда я пытаюсь скомпилировать это я получаю следующее:

<console>:10: error: too many arguments for method apply: (value: T)Node[T] in object Node

    def apply[T](value: T): Node[T] = Node(value, End, End)

Если я удаляю оба Конца, я не получаю никаких ошибок компиляции, но если я делаю Узел с единственным значением, я застреваю в бесконечном цикле. Так что, похоже, apply создает больше объектов Node и не ассоциирует себя с классом Node.

Любая помощь приветствуется.

sealed abstract class Tree[+T]
case class Node[+T](value: T, left: Tree[T], right: Tree[T]) extends Tree[T] {
    override def toString = "T(" + value.toString + " " + left.toString + " " + right.toString + ")"
}
case object End extends Tree[Nothing] {
    override def toString = "."
}
object Node {
    def apply[T](value: T): Node[T] = Node(value, End, End)
}

1 Ответ

12 голосов
/ 09 июня 2011

У меня работает (см. Ниже). Вы определили их в одном файле?


Welcome to Scala version 2.9.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_24).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :paste
// Entering paste mode (ctrl-D to finish)

sealed abstract class Tree[+T]
case class Node[+T](value: T, left: Tree[T], right: Tree[T]) extends Tree[T] {
    override def toString = "T(" + value.toString + " " + left.toString + " " + right.toString + ")"
}
case object End extends Tree[Nothing] {
    override def toString = "."
}
object Node {
    def apply[T](value: T): Node[T] = Node(value, End, End)
}

// Exiting paste mode, now interpreting.

defined class Tree
defined class Node
defined module End
defined module Node

scala> Node("123")
res0: Node[java.lang.String] = T(123 . .)

scala>

Редактировать Из вашего комментария: похоже, что команда :load в repl интерпретирует каждую строку в файле один за другим, вы можете найти код для этого здесь . Однако это не работает с использованием REPL, поскольку (я полагаю) каждая интерпретируемая строка компилируется в свой собственный пакет. См. эту тему для более подробной информации. Возможно, это может стать будущим улучшением в REPL. Но в принципе в вашем коде нет ничего плохого: использование режима :paste или просто компиляция с scalac работает нормально.


scala> case class A(i: Int, i2: Int)
defined class A

scala> object A {
     | def apply(i: Int): A = A(i, i)
     | }
:25: error: too many arguments for method apply: (i: Int)A in object A
       def apply(i: Int): A = A(i, i)

scala> object A {
         def apply(i: Int): A = new A(i, i)
       }
defined module A
warning: previously defined class A is not a companion to object A.
Companions must be defined together; you may wish to use :paste mode for this.

Примечание. Я не смог найти ни одного запроса на улучшение JIRA, поэтому создал эту проблему

...