Как сделать только несколько типов данных, не связанных друг с другом, приемлемыми для дженериков
Есть черта, которая работает отлично. Тем не менее, я хотел бы реорганизовать часть, относящуюся к generic [T], чтобы ограничить тип данных, который может быть принят generic [T] (мне нужны только Option[JsValue], JsValue, StringEnumEntry, String). Можно ли решить эту проблему с помощью бесформенного побочного продукта? Может быть есть другие решения?
trait ParameterBinders extends Log {
def jsonBinder[T](json: T, jsonType: java.lang.String = "json"): ParameterBinderWithValue = {
val jsonObject = new PGobject()
jsonObject.setType(jsonType)
json match {
case json: Option[JsValue] =>
jsonObject.setValue(json.map(Json.stringify).orNull)
case json: JsValue =>
jsonObject.setValue(Json.stringify(json))
case json: StringEnumEntry =>
jsonObject.setValue(json.value)
case json: String =>
jsonObject.setValue(json)
case _ =>
logger.error("unexpected data type ")
}
if (jsonType == "JSONSCHEMATYPE" || jsonType == "SYSPROPERTYTYPE") {
ParameterBinder(this, (ps, i) => {
ps.setObject(i, jsonObject)
})
} else {
ParameterBinder(json, (ps, i) => {
ps.setObject(i, jsonObject)
})
}
}
}
1 ответ
Самый простой способ - использовать ADT, как описано в ссылке первого комментария. Если вы не хотите менять типы, которые принимаются в jsonBinder
тогда вы можете решить проблему, используя класс типов.
например
trait JsonBindValue[T] {
def value(t: T): String
}
Затем вам нужно будет предоставить экземпляры для ваших принятых типов данных
object JsonBindValue {
implicit val OptJsBinder = new JsonBindValue[Option[JsValue]] {
def value(t: Option[JsValue]): String = {
t.map(Json.stringify).orNull
}
}
... more instances here
}
наконец ваша функция будет выглядеть так:
def jsonBinder[T : JsonBindValue](json: T, jsonType: java.lang.String = "json"): ParameterBinderWithValue = {
val binder = implicitly[JsonBindValue[T]]
jsonObject.setType(jsonType)
jsonObject.setValue(binder.value(json))
...
}
если вы вызываете функцию без неявного экземпляра в области видимости, вы получите ошибку времени компиляции.