如何仅使泛型可接受彼此不相关的少数数据类型
How to make only few datatype which is not related to each other acceptable by generics
有一个特性非常有效。但是,我想重构与泛型 [T] 相关的部分,以限制泛型 [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)
})
}
}
}
最简单的方法是按照第一条评论的 link 中所述使用 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))
...
}
如果在作用域中调用没有隐式实例的函数,将会出现编译时错误。
有一个特性非常有效。但是,我想重构与泛型 [T] 相关的部分,以限制泛型 [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)
})
}
}
}
最简单的方法是按照第一条评论的 link 中所述使用 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))
...
}
如果在作用域中调用没有隐式实例的函数,将会出现编译时错误。