我对Scala相当新,但是从我到目前为止看到的代码中遇到了一种编码模式。以下是我所谈论的一个例子:
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类。 为什么这样做?有什么好处,它真的是一种模式,还是我还没有深入到完全理解的东西?
感谢一帮!
答案 0 :(得分:1)
如果您来自Java背景,static
成员将是最接近的类比。
对于类,类中的嵌套类可能具有对所有者对象的隐式引用;另外,它可以访问封闭对象的字段。对于object
范围内的课程,您没有这种风险,因此错误发生的可能性要小得多。
同样,您在class
中定义的所有内容只能作为该类实例的一部分进行测试。因此,您的测试需要实例化该类,为event
提供一些值(这对于大多数测试没有多大意义,增加了杂乱),而对于object
成员,您只需要指的是那里的成员 - 他们有权访问的状态非常有限,他们需要实例化的状态是已经存在。
PS。顺便提一下,Props(new TicketSeller(event))
是另一个很好的榜样。它在这里完成的方式是完全正常,但是如果你把它移到类本身,它就会变成dangerous variant,原因完全相同:封闭类的可见性' s状态太容易关闭封闭的范围。
// NOT RECOMMENDED within another actor: // encourages to close over enclosing class val props7 = Props(new MyActor)
不建议在另一个actor中使用此方法,因为它鼓励关闭封闭范围,导致不可序列化的Props和可能的竞争条件(打破actor封装)。我们将在未来版本中提供基于宏的解决方案,该解决方案允许类似的语法而不会令人头疼,此时将适当地弃用此变体。另一方面,如下面“推荐实践”中所述,在演员的伴侣对象的道具工厂中使用此变体是完全正常的。