пересылать ссылки на классы в Scala? - PullRequest
6 голосов
/ 31 октября 2010

Я сталкиваюсь со стандартной проблемой как новичок в Scala: как определить два класса таким образом, чтобы я мог создать экземпляр одного класса, а другой - переменную-член, которая, в свою очередь, указывает на первый экземпляр

Я бы хотел закончить экземпляр игры который имеет член типа Dealer который имеет член типа Game, который фактически является оригинальным экземпляром Game

Таким образом, в этом случае каждый экземпляр (Game, Dealer) имеет члена, который является другим экземпляром. Кто-нибудь может направить меня к правильному пути к этому?

Ответы [ 3 ]

8 голосов
/ 31 октября 2010

Если вам действительно нужно сделать классы неизменяемыми, ваш единственный вариант - использовать параметры по имени в конструкторе и всегда создавать экземпляры как ленивые val s:

class Dealer(val name: String, g: => Game) {
  lazy val game = g
  override def toString = "Dealer(name=%s, game=%s)".format(name, game.name)
}

class Game(val name: String, d: => Dealer) {
  lazy val dealer = d
  override def toString = "Game(name=%s, dealer=%s)".format(name, dealer.name)
}

lazy val game: Game = new Game("Doppelkopf", new Dealer("Peter", game))
lazy val dealer: Dealer = new Dealer("Tina", new Game("Poker", dealer))

Обратите внимание, что вам нужно ввести тип для lazy vals, иначе он не скомпилируется.

3 голосов
/ 31 октября 2010

У вас есть два варианта:

  1. Сделайте ваши объекты изменчивыми, а затем просто используйте те же приемы, что и в Java.
  2. Сделайте их неизменными, затем отбросьте двусторонние зависимости.

Чтобы понять почему, рассмотрим следующее преобразование между (неизменяемыми) деревьями. Оба они определены с каждым родительским узлом, содержащим список дочерних узлов, но дети не знают своего родителя :

a               (a)
  b               (b)
    c                c
    d     -->       (d) 
  e                e
    f                f
    g                g

В частности, узел d был клонирован с новым значением. Для этого нам также пришлось клонировать все родительские узлы (показано в скобках).

Если бы узлы содержали своего родителя, тогда c необходимо было бы "обновить", чтобы отразить новый узел b, а e, f, g пришлось бы обновить, чтобы отразить новый узел a. т.е. все дерево должно быть скопировано!

Удерживая отношения только в одном направлении от родителя к ребенку, становится возможным повторное использование c, e, f, g в последующих версиях структуры. Это мощная оптимизация и ключ к написанию эффективных функциональных алгоритмов.

2 голосов
/ 31 октября 2010

Я думаю, что вы говорите о «двухсторонней» зависимости, и это легко сделать, если максимально одна из сущностей является неизменной (если вы хотите, чтобы обе были неизменяемыми, вы должны увидеть решение Moviz).

В моем примере я позволил Game быть неизменной сущностью. Дилер может не участвовать в игре.

class Dealer(val name: String){
  var game: Option[Game] = None
}

case class Game(name: String, dealer: Dealer)

// Instanciate the game and the dealer
val olle = new Dealer("Olle")
val ollesGame = Game("Olles Game", olle)
olle.game = Some(ollesGame)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...