2015-06-18 5 views
0

Это проблема совпадения рисунков внутри Получателя акка.Каков тип класса внутри объекта внутри черты

У меня есть этот код:

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.Result, Customer.Get.Result, когда он получает первый один все идет найти, но когда второй приходит он бросает и исключение, которое Customer может бросить до Entry, это потому, что первые сообщения были пойманы первым case.

Затем я изменю получить с

def receive: Actor.Receive = test 

как сообщение показывает то же имя класса GenericMessages$Get$Result, так вот почему оба сообщения попадают в первую case.

Я пытаюсь создать общий case для обоих сообщений с GenericMessages#Get, но это делает ссылки на класс Get внутри GenericMessages вместо объекта Get.

Итак, мой вопрос: есть ли способ ссылаться на класс Result внутри объекта Get объекта GenericMessages? Есть ли другой способ, которым я мог бы сделать case, чтобы избежать этой проблемы с совпадением шаблонов?


Дополнительная информация: Настоящий актер является реализация родового актера, потому что мне нужно такое же поведение в других актеров.

Сообщения Entry.Get.Result, Customer.Get.Result являются ответы предыдущего сообщения отправить на тот же актер (anotherActor ! Customer.Get) и реализуется таким образом, потому что я предпочитаю параллельные вызовы по сравнению с линейными вызовами. Линейное решение состоит в том, чтобы иметь один метод для приема первого сообщения, чем использовать become, чтобы изменить на другое получение и обработать второе сообщение. Я хочу избежать этого линейного подхода, потому что 1. Я предпочитаю, чтобы это был параллельный процесс, и 2. он нарушает абстракцию, которую я сделал.

+0

Не так, как говорят «я выделяю Откуда Лонга в двух разных классах?» Они по сути то же самое, не так ли? Должен быть какой-то внешний способ (не в длинном экземпляре), чтобы определить, к какому классу принадлежит Long. – bjfletcher

ответ

0

Я нашел решение.

я решил добавить третий 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 
    } 
} 

теперь он работает, как это необходимо.


Полный код:

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

    def receive: Actor.Receive = messages 

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

private object Messages extends GenericMessages[AppAny] 
//I still need this two objects because they are part of 
//other service that use this messages 
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 
0

Существует одно решение (что очень некрасиво): Сделайте запись и клиента на классы:

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

затем создать запись и клиента экземпляра:

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

и передавать их в качестве параметров ваш актерский рецензирующий актер (и anybidy, которому это нужно). Затем создайте и соответствовать следующим образом:

entry.Get.Result 
customer.Get.Result 

Но это плохой дизайн.

Предлагаю избегать дженериков при работе с актерами. Стирание типа становится проблемой, когда вам нужно сопоставлять типы во время выполнения. Если бы я был вами, я бы пересмотрел дизайн.

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