Scala/Akka 组合模式(class 中的对象)
Scala/Akka composition pattern (object in class)
我是 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 class 如何从 TicketSeller object
导入所有东西
import TicketSeller._
我之前见过这种 "object in class" 模式,其中对象中的大部分(如果不是全部)都是大小写 classes。
为什么要这样做?有什么好处,它真的是一种模式,还是我对事物的了解不够深入,无法完全理解?
非常感谢!
如果您来自 Java 背景,static
成员将是最接近的类比。
在 classes 的情况下,class 中的嵌套 class 可能具有对所有者对象的隐式引用;此外,它还可以访问封闭对象的字段。如果 object
中有 class,则没有这种风险,因此出错的可能性要小得多。
同样,您在 class
中定义的所有内容都只能作为 class 的 实例 的一部分进行测试。因此,您的测试将需要实例化 class,为 event
提供一些值(这对大多数测试来说没有多大意义,增加了混乱),而 object
members 你只是指那里的任何成员——他们可以访问的状态非常有限,他们需要实例化的状态已经存在.
PS。顺便说一下,Props(new TicketSeller(event))
是另一个很好的例子。这里的做法是 完全没问题, 但是如果你把它移到 class 本身,它会变成 dangerous variant 原因完全相同:可见性封闭 class 的状态使得关闭封闭范围太容易了。
// NOT RECOMMENDED within another actor:
// encourages to close over enclosing class
val props7 = Props(new MyActor)
This method is not recommended to be used within another actor because it encourages to close over the enclosing scope, resulting in non-serializable Props and possibly race conditions (breaking the actor encapsulation). We will provide a macro-based solution in a future release which allows similar syntax without the headaches, at which point this variant will be properly deprecated. On the other hand using this variant in a Props factory in the actor’s companion object as documented under “Recommended Practices” below is completely fine.
我是 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 class 如何从 TicketSeller object
导入所有东西 import TicketSeller._
我之前见过这种 "object in class" 模式,其中对象中的大部分(如果不是全部)都是大小写 classes。 为什么要这样做?有什么好处,它真的是一种模式,还是我对事物的了解不够深入,无法完全理解?
非常感谢!
如果您来自 Java 背景,static
成员将是最接近的类比。
在 classes 的情况下,class 中的嵌套 class 可能具有对所有者对象的隐式引用;此外,它还可以访问封闭对象的字段。如果 object
中有 class,则没有这种风险,因此出错的可能性要小得多。
同样,您在 class
中定义的所有内容都只能作为 class 的 实例 的一部分进行测试。因此,您的测试将需要实例化 class,为 event
提供一些值(这对大多数测试来说没有多大意义,增加了混乱),而 object
members 你只是指那里的任何成员——他们可以访问的状态非常有限,他们需要实例化的状态已经存在.
PS。顺便说一下,Props(new TicketSeller(event))
是另一个很好的例子。这里的做法是 完全没问题, 但是如果你把它移到 class 本身,它会变成 dangerous variant 原因完全相同:可见性封闭 class 的状态使得关闭封闭范围太容易了。
// NOT RECOMMENDED within another actor: // encourages to close over enclosing class val props7 = Props(new MyActor)
This method is not recommended to be used within another actor because it encourages to close over the enclosing scope, resulting in non-serializable Props and possibly race conditions (breaking the actor encapsulation). We will provide a macro-based solution in a future release which allows similar syntax without the headaches, at which point this variant will be properly deprecated. On the other hand using this variant in a Props factory in the actor’s companion object as documented under “Recommended Practices” below is completely fine.