Я пытаюсь смоделировать ответы от REST API как кейс-классы, для которых я могу использовать сопоставление с образцом.
Я думал, что было бы неплохо принять наследование, но я вижу, что это устарело. Я знаю, что уже есть вопросы, связанные с case-классами и наследованием, но мой вопрос больше о том, как вы могли бы смоделировать следующий «правильный путь» здесь без наследования.
Я начал со следующих двух case-классов, которые отлично работают:
case class Body(contentType: String, content: String)
case class Response(statusCode: Int, body: Body)
т. е. вызов REST будет возвращаться с чем-то вроде:
Response(200, Body("application/json", """{ "foo": "bar" }"""))
который я мог бы сопоставить с шаблоном, например:
response match {
case Response(200, Body("application/json", json)) => println(json)
case Response(200, Body("text/xml", xml)) => println(xml)
case Response(_,_) => println("Something unexpected")
}
и т. д., который работает нормально.
Вот где я столкнулся с проблемой: мне нужны вспомогательные расширения для этих классов case, такие как:
case class OK(body: Body) extends Response(200, body)
case class NotFound() extends Response(404, Body("text/plain", "Not Found"))
case class JSON(json: String) extends Body("application/json", json)
case class XML(xml: String) extends Body("text/xml", xml)
, чтобы я мог выполнять упрощенные сопоставления шаблонов, например:
response match {
case OK(JSON(json)) => println(json)
case OK(XML(xml)) => println(xml)
case NotFound() => println("Something is not there")
// And still drop down to this if necessary:
case Response(302, _) => println("It moved")
}
, а также которые также позволяли бы использовать мой REST-код. для прямого использования и возврата:
Response(code, Body(contentType, content))
, что упрощает динамическое построение ответа.
Итак...
Я могу заставить его скомпилироваться (с предупреждениями об устаревании) с помощью:
case class OK(override val body: Body) extends Response(200, body)
Однако, похоже, это не работает с сопоставлением с образцом.
Response(200, Body("application/json", "")) match {
case OK(_) => ":-)"
case _ => ":-("
}
res0: java.lang.String = :-(
Есть идеи, как это могло бы работать? Я открыт для разных подходов, но это была моя попытка найти практическое применение кейс-классам