特征内部对象内部的类型是什么

时间:2015-06-18 23:57:48

标签: scala casting pattern-matching akka

这是一个akka演员的接收中的模式匹配问题。

我有这段代码:

class ActorReservation(reservation: Reservation) extends Actor {
  import Entry._
  import Customer._

  def receive: Actor.Receive = messages

  def messages: Receive = {
    case Entry.Get.Result(obj) => // process entry

    case Customer.Get.Result(obj) => // process customer
  }

  def test: Receive = {
    case e =>
      println(s"ClassName -> ${e.getClass.getName}")
      println(s"isInstanceOf[GenericMessages#Get] -> ${isInstanceOf[GenericMessages[AppAny]#Get]}")
  }
}

object Entry extends GenericMessages[EntryEntity]
object Customer extends GenericMessages[CustomerEntity]

trait GenericMessages[A <: AppAny] {
  case class Get(id: Int)
  object Get { case class Result(obj: Option[A]) }
} //trait

trait AppAny
case class EntryEntity(id: Int) extends AppAny
case class CustomerEntity(id: Int) extends AppAny

我的演员可以收到两条消息:Entry.Get.ResultCustomer.Get.Result,当它收到第一个消息时,一切都会找到,但是当第二个消息到达时,它会抛出Customer可以强制转换的异常Entry,这是因为第二封邮件已被第一封case抓住。

然后我用

更改接收
  def receive: Actor.Receive = test

这两条消息都显示相同的类名GenericMessages$Get$Result,这就是为什么这两个消息都属于第一个case

我尝试为case的两封邮件创建通用GenericMessages#Get,但这会引用Get内的GenericMessages类,而不是对象Get

所以,我的问题是:有没有办法在Result特征的Get对象中引用GenericMessages类?还有另一种方法可以让case避免这种模式匹配问题吗?

其他信息: 真正的actor是泛型actor的实现,因为我需要在其他actor中使用相同的行为。

消息Entry.Get.ResultCustomer.Get.Result是同一个参与者(anotherActor ! Customer.Get)发送的先前消息的响应,并以这种方式实现,因为我更喜欢并行调用而不是线性调用。线性解决方案是使用一种方法来接收第一条消息,而不是使用become来更改为另一条接收并处理第二条消息。我想避免这种线性方法,因为1.我更喜欢它是一个并行过程而且2.它打破了我所做的抽象。

2 个答案:

答案 0 :(得分:0)

有一个解决方案(非常难看):让入门和客户进入班级:

case class Entry() extends GenericMessages[EntryEntity]
case class Customer() extends GenericMessages[CustomerEntity]

然后创建一个条目和客户实例:

val entry = Entry()
val customer = Customer()

并将它们作为参数传递给您的ActorReservation actor(以及需要它的anybidy)。然后像这样创建和匹配:

entry.Get.Result
customer.Get.Result

但这是糟糕的设计。

我建议在与演员合作时避免使用泛型。当您需要在运行时匹配类型时,类型擦除会成为问题。 如果我是你,我会重做设计。

答案 1 :(得分:0)

我找到了解决方案。

除了 var applicationView = ApplicationView.GetForCurrentView(); var titleBar = applicationView.TitleBar; CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true; titleBar.ButtonBackgroundColor = Colors.Transparent; titleBar.ButtonForegroundColor = Colors.White; object

之外,我决定添加第三个Entry
Customer

并使用此

更改接收功能
private object Messages extends GenericMessages[AppAny]

现在它可以根据需要运行。

完整代码:

def messages: Receive = {
  case Messages.Get.Result(obj) => 
    obj match {
      case Some(e: Entry) =>     // process entry
      case Some(c: Customer) =>  // process customer
    }
}