2016-06-04 6 views
2

Я довольно новичок в Scala, но столкнулся с каким-то кодом кодирования из кода, который я видел до сих пор. Вот пример того, что я говорю:Шаблон композиции Scala/Akka (объект в классе)

object TicketSeller { 
    def props(event: String) = Props(new TicketSeller(event)) 

    case class Add(tickets: Vector[Ticket]) 

    case class Buy(tickets: Int) 

    case class Ticket(id: Int) 

    case class Tickets(event: String, 
        entries: Vector[Ticket] = Vector.empty[Ticket]) 

    case object GetEvent 

    case object Cancel 

} 

class TicketSeller(event: String) extends Actor { 

    import TicketSeller._ 

    var tickets = Vector.empty[Ticket] 

    def receive = { 
    case Add(newTickets) => tickets = tickets ++ newTickets 
    case Buy(nrOfTickets) => 
     val entries = tickets.take(nrOfTickets).toVector 
     if (entries.size >= nrOfTickets) { 
     sender() ! Tickets(event, entries) 
     tickets = tickets.drop(nrOfTickets) 
     } else sender() ! Tickets(event) 
    case GetEvent => sender() ! Some(BoxOffice.Event(event, tickets.size)) 
    case Cancel => 
     sender() ! Some(BoxOffice.Event(event, tickets.size)) 
     self ! PoisonPill 
    } 
} 

Обратите внимание, как TicketSeller класса импортирует все вещи из объекта TicketSeller

import TicketSeller._ 

Я видел этот «объект в классе» шаблон, в котором большинство, если не все вещи в объекте, являются классами case. Почему это делается так? Каковы преимущества и действительно ли это образец, или я недостаточно глубоко разбираюсь в вещах, чтобы их полностью понять?

Спасибо, связка!

ответ

1

Если вы исходите из фона Java, static членов будет ближайшей аналогией.

В случае классов вложенный класс класса может иметь неявную ссылку на объект владельца; Кроме того, он может получить доступ к полям закрытого объекта. В случае класса в пределах object у вас нет такого риска, поэтому гораздо меньше шансов на ошибку.

Аналогично, все, что вы определяете в class, может быть проверено только как часть экземпляра этого класса. Таким образом, ваши тесты должны будут создавать экземпляр класса, придумывая какое-то значение для event (что не имеет большого смысла для большинства тестов, добавляя к беспорядку), тогда как с членами object вы просто ссылаетесь на то, что есть у членов - состояние, к которому они имеют доступ, очень ограничено, и состояние, которое им нужно создать, - уже есть.

PS. Props(new TicketSeller(event)), кстати, делает еще один отличный пример. То, как это делается здесь, является полностью прекрасным,, но если вы переместите его на сам класс, он станет dangerous variant по той же причине: видимость состояния охватывающего класса делает его слишком простым для закрытия по охватывающей области.

// NOT RECOMMENDED within another actor: 
// encourages to close over enclosing class 
val props7 = Props(new MyActor) 

Этого метод не рекомендуются использовать внутри другого актера, потому что она стимулирует, чтобы закрыть над заключающим объемом, что приводит к несериализуемому реквизиту и, возможно, условиям гонки (разрыв актера инкапсуляции). Мы предоставим решение на основе макросов в будущей версии, которое позволит использовать аналогичный синтаксис без головных болей, после чего этот вариант будет должным образом устаревать. С другой стороны, использование этого варианта на фабрике реквизита в сопутствующем объекте актера, как описано в «Рекомендуемой практике» ниже, полностью прекрасное.

+0

Использование 'Props (new MyActor)' опасно только в том случае, если вы делаете это внутри другого Актера. В вашей ссылке упоминается, что способ, которым @Alexandr использует его, внутри объекта-компаньона, является рекомендуемой практикой. – rgcase

+0

Достаточно честный; Сегодня я перефразирую. – alf

+0

Большое спасибо! – Alexandr

 Смежные вопросы

  • Нет связанных вопросов^_^