我一直在讨论从3种方法中重构公共代码并进入makeRequest()
的问题,但是我从编译器得到了模糊的隐式匹配。我不确定这是否来自隐式方法或其他问题的默认值,但我的目标是getRequest / deleteRequest / postRequest可以简单地调用makeRequest(" GET")/ makeRequest(" DELETE& #34;)/ makeRequest的(" POST&#34)。以前没有任何参数是隐含的,我只是试图通过使用implicits来达到目标
def makeRequest(method: String)(implicit path: String, base: String, params: Seq[(String, String)], body: Option[String], retriesLeft: Int): Future[WSResponse] = ???
def getRequest()(implicit path: String, base: String = baseUrl, params: Seq[(String, String)] = Seq(), body: Option[String] = None, retriesLeft: Int = retries): Future[WSResponse] = makeRequest("GET")
def deleteRequest()(implicit path: String, base: String = baseUrl, params: Seq[(String, String)] = Seq(), body: Option[String] = None, retriesLeft: Int = retries): Future[WSResponse] = makeRequest("GET")
def postRequest[T]()(path: String, body: T, base: String = baseUrl, params: Seq[(String, String)] = Seq(), retriesLeft: Int = retries)
(implicit wrt: play.api.http.Writeable[T], ct : play.api.http.ContentTypeOf[T]): Future[WSResponse] = makeRequest("POST")
我得到这个和deleteRequest一样
ambiguous implicit values:
[error] both value base of type String
[error] and value path of type String
[error] match expected type String
[error] def getRequest()(implicit path: String, base: String = baseUrl, params: Seq[(String, String)] = Seq(), body: Option[String] = None, retriesLeft: Int = retries): Future[WSResponse] = makeRequest("GET")
答案 0 :(得分:9)
我认为你应该重新使用所有这些隐含的,除非你正在做一些非常时髦的DSL。
这是解决您遇到的问题的一种方法。正如您可能已经猜到的那样,对Type的隐式工作而不是名称,因此具有两个隐式具有相同类型的是No-No。
自Scala 2.10起,Scala允许您使用AnyVal(SIP-15)“内联”类。以下是所谓的值类的示例:
case class Path(p: String) extends AnyVal
现在不用使用字符串来表示你的实体,而是将它们包含在这个漂亮的“包装器”类中。关于这一点很酷的是编译器将在编译期间用String替换代码中的所有Path对象。因此,就编译代码而言,您将获得与使用String时相同的性能。您可以获得很多类型安全性而无需支付运行时间罚款。
现在回到你的案例,这里是如何解决你的问题:
case class Path(s: String) extends AnyVal
case class BaseUrl(s: String) extends AnyVal
def foo(implicit a: Path, b: BaseUrl) = a.s ++ b.s
implicit val a: Path = Path("a")
implicit val b: BaseUrl = BaseUrl("b")
以下是如何使用它:
scala> foo
res0: String = ab
答案 1 :(得分:2)
正如Marios所说,问题在于你对String和Int等类型使用了implicits。由于implicits在类型而不是名称上工作,编译器不知道在哪里放置'隐式字符串'。 这就是应该使用自定义类型的原因。我从上一次ScalaDays会议中拿走的一件事是你应该为所有东西创建类型,因为编译器可以帮助你验证你的程序是否正确。
然而,看看你的解决方案,我根本不会使用含义。最好使用单个参数列表并为所有或大多数值提供默认值。然后'makeRequest'可以默认执行'Get /',并且可以通过提供'path =“/ search”'或'method =“POST”'来改变此行为。
也可以为http方法使用某种范围类型,因为您已经知道了哪些有效值以及您想要支持哪些有效值。