Можно ли получить кортеж внутри актера без предупреждения "устранено стиранием"

Интересно, возможно ли получить кортеж внутри актера, не получив это предупреждение:

non-variable type argument Long in type pattern (Long, Int) is unchecked since it is eliminated by erasure

хотя код кажется действительным и работает:

override def receive: Receive = {
  case tuple: (Long, DateTime) => sendPlace(tuple._1, tuple._2)
}

Я что-то пропустил?

2 ответа

Решение

Пишу

case (id: Long, time: DateTime) => sendPlace(id, time)

также позволит избежать неконтролируемых приведений, но Лукаш прав: для этого вы должны определить класс дел.

так как два приложения обмениваются данными друг с другом, это позволяет мне не определять дважды класс случая

Конечно, вы не должны определять это дважды. Определите его один раз в библиотеке, от которой зависят оба приложения. Таким образом, 1) вы ясно указываете, где приложения общаются; 2) если вам нужно изменить тип сообщения (например, добавить другое поле или изменить тип одного из полей), вы с гораздо меньшей вероятностью забудете изменить одну из сторон.

Не могли бы вы, пожалуйста, объяснить, почему я не получаю это предупреждение, если оно не в контексте актера, который получает сообщение?

Ты сделаешь:

val x: Any = ("a", "b")

x match {
  case tuple: (Long, DateTime) => 
    println("shouldn't match, but does")
}

Кортежи являются общими типами, например Tuple2[T1, T2] и в JVM эти параметры типа стираются и не присутствуют во время выполнения. Есть много на эту тему онлайн.

Ваш код работает, но проверяется, соответствует ли сообщение шаблону, только если Tuple2, а не внутренние ее типы. Если этот актер получает другой Tuple2, сказать (String, String) вы получите исключение приведения класса при попытке конвертировать String, чтобы Long при попытке передать первый элемент sendPlace метод.

Например, в следующем

override def receive: Receive = {
  case tuple: (Long, DateTime) => sendPlace(tuple._1, tuple._2)
  case tuple: (Int, Int) => sender ! (tuple._1 + tuple._2)
}

второй шаблон недоступен, он никогда не будет совпадать, как любой Tuple2 будет соответствовать первому шаблону и выдавать исключение, если тип неправильный.

В общем случае вы должны создавать классы case для сообщений. Преимущество этого сообщения состоит в том, что оно имеет смысл как для сообщения, так и для его членов, а кортеж ничего не говорит, кроме его типов. Вы должны определить сообщения, которые субъект может обработать в своем объекте-компаньоне.

object BookingActor {
  case class BookingRequest(placeId: Long, bookingTime: DateTime)
}

class BookingActor {
  import BookingActor._

  override def receive: Receive = {
    case BookingRequest(id, time) => bookPlace(id, time)
  }

  // ...
}
Другие вопросы по тегам