Можно ли получить кортеж внутри актера без предупреждения "устранено стиранием"
Интересно, возможно ли получить кортеж внутри актера, не получив это предупреждение:
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)
}
// ...
}