3

有一个完美的特质。但是,我想重构与泛型 [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)
      })
    }

  }
}
4

1 回答 1

2

最简单的方法是使用第一条评论链接中描述的 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))
    ...
}

如果您在范围内没有隐式实例的情况下调用该函数,您将收到编译时错误。

于 2018-07-02T10:11:42.667 回答