2016-08-10 3 views
1

3つのメソッドのうち共通のコードをリファクタリングする問題に遭遇しましたが、makeRequest()にコンパイルされた暗黙の暗黙的な一致があります。私はこれが暗黙のメソッドまたは他のいくつかの問題のデフォルトを持っているかどうかはわかりませんが、私の目標はgetRequest/deleteRequest/postRequestは単にmakeRequest( "GET")/ makeRequest( "DELETE")/ makeRequest( "POST" )。以前のパラメータのどれもが暗黙の、私はちょうど使用して暗黙 デフォルト値を持つ複数の暗黙的なパラメータがあいまいな値を返す

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") 
+1

目立つ赤い旗の1つは、 'String'に'暗黙的 'が必要だということです。できるだけ一般的な型に対する暗黙的な定義を避けてください。つまり、あいまいな暗黙的な暗黙をデバッグするには、上記の方法のサイトを参照し、範囲内のすべてのimplicitsを見つけるので、あなたが私たちに提供した情報は十分ではありません。 – Alec

+0

@Alec、私はこのコメントの後のポストでこれを明らかにするだろうが、以前はgetRequest/deleteRequest/postRequestに明示的なパラメータしかなかったので、私は各メソッドを単に呼び出すようにmakeRequestに3つのメソッドの共通コードをリファクタリングしようとしている。 makeRequest( "GET")。これを行うには、implicitsを使用しようとしています – irregular

+3

Implicitsは名前ではなくタイプのみで検索するので、 'String'を使用すると期待どおりに動作しません。 – Reactormonk

答えて

7

と私はあなたがすべてのこれらの暗黙のを使用して再検討すべきだと思います本当にファンキーなDSLをやっていない限り。

ここにある問題を解決する方法の1つです。あなたが推測しているかもしれないが、名前ではなくタイプで暗黙的に働くので、同じタイプで暗黙のうちに2つの暗黙のものはNo-Noです。

Scala 2.10以降、ScalaではAnyVal(SIP-15)を使用してクラスをインライン化できます。

case class Path(p: String) extends AnyVal 

今の代わりに、あなたのエンティティを表現するために文字列を使用して、あなたは、この素敵な「ラッパー」クラスでそれらを囲みます。ここでは、いわゆる値クラスの例があります。これについての素晴らしい点は、コンパイル時に、コンパイラがコード内のすべてのPathオブジェクトをStringで置き換えることです。したがって、コンパイルされたコードに関しては、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

タイプをラップするヒントは非常に有益でした!今のところ、各パラメータのケースクラスを追加するとボイラープレートのコードのように思えるので、暗黙的でない値を使用します。これは間違いなく私にインプリケートがどのように働くかについてより多くの洞察を与えました – irregular

1

マリオスが言うように、問題があることですあなたはStringやIntのような型のimplicitsを使っています。 implicitsは名前ではなく型で動作するので、コンパイラは '暗黙のString'をどこに置くべきかを知りません。 そのため、カスタムタイプを使用する必要があります。前回のScalaDaysカンファレンスで取り上げたことの1つは、コンパイラがプログラムが正しいかどうかを確認するのに役立つので、すべてのタイプを作成する必要があるということです。

しかし、あなたのソリューションを見ても、私は暗黙のうちには何も使用しません。単一の引数リストを使用し、すべてまたはほとんどの値のデフォルトを提供する方が良いでしょう。次に 'makeRequest'はデフォルトで 'Get /'を行い、この動作は 'path = "/ search"'や 'method = "POST"'などのように変更することができます。

有効な値とサポートしている値がすでに分かっているので、httpメソッドのスコープ付きタイプを使用してください。

関連する問題