2

私はこれを実装しようとしています:

def buildQuery() {
  val restrictions: ConjunctionRestriction[String, Int] =
    ("name" is "Some One") and ("age" is 20)
}

implicit def stringToEqualsRestrictionBuilder[T](fieldName: String)
                                                : EqualsRestrictionBuilder[T] =
  new EqualsRestrictionBuilder[T](fieldName)

implicit def restrictionToConjunctionBuilder[L,R](restriction: Restriction[L])
                                                 : ConjunctionBuilder[L,R] =
  new ConjunctionBuilder[L,R](restriction)

case class Restrictions(restrictions: Restriction[_]*)

trait Restriction[T] {
  def toString: String
}

class EqualsRestriction[T](val fieldName: String, val value: T)
    extends Restriction[T] {
  override def toString = fieldName + "=" + value
}

class ConjunctionRestriction[A,B](val lhs: Restriction[A],
                                  val rhs: Restriction[B]) 
    extends Restriction[(A,B)] {
  override def toString = "(" + lhs + ") AND (" + rhs + ")"
}

class EqualsRestrictionBuilder[T](val fieldName: String,
                                  val restriction: Option[Restriction[T]] = None) {

  def is(value: Int) =
    new EqualsRestriction[Int](fieldName, value)

  def is(value: String) =
    new EqualsRestriction[String](fieldName, "\"" + value + "\"")
}

class ConjunctionBuilder[L,R](val lhs: Restriction[L]) {
  def and(rhs: Restriction[R]) = new ConjunctionRestriction[L,R](lhs, rhs)
}

コンパイラは私にエラーを与えます:

error: type mismatch;
found   : MyOuterClass.this.EqualsRestriction[Int]
required: MyOuterClass.this.Restriction[R]
val restrictions: ConjunctionRestriction[String, Int] =
  ("name" is "Some One") and ("age" is 20)

私は、scala 型システムをすべて把握していません。これの何が問題なのですか?

ありがとう

編集

ConjunctionBuilder を変更して、パラメータ タイプ L を 1 つだけ持つように修正しました。

class ConjunctionBuilder[L](val lhs: Restriction[L]) {
  def and[R](rhs: Restriction[R]) = new ConjunctionRestriction[L,R](lhs, rhs)
}

implicit def restrictionToConjunctionBuilder[L](restriction: Restriction[L])
                                               : ConjunctionBuilder[L] =
  new ConjunctionBuilder[L](restriction)

しかし、誰かが R パラメータ型でコンパイルが失敗する理由を説明できますか?

4

1 に答える 1

3

暗黙の変換を適用する場合、コンパイラは(パラメータから)推測することしかできないためConjunctionBuilder、typeパラメータがある場合は失敗します。タイプパラメータはパラメータリストのどこにも表示されないため、推測することはできません。型パラメーターを推測できない場合は、明示的に渡す必要があります(ただし、暗黙的な変換の場合は、もちろん目的が果たせません)。例:以下は正しくコンパイルされます:RrestrictionToConjunctionBuilderLrestrictionR

val restrictions: ConjunctionRestriction[String, Int] =
  (("name" is "Some One"): ConjunctionBuilder[String, Int]) and ("age" is 20)

型パラメーターを明示的に指定しない限り、コンパイラーはバインドできず、したがって、メソッドへのパラメーターが正しい型であるRことを証明できません。and確かに、メソッドはを期待しRestriction[R]、それにを与えますRestriction[Int]Rこれは、 ==の場合にのみ一致します。これは、コンパイラーがバインドIntされていないことを証明できません。R

修正は完全に正しいです。typeパラメーターRをの定義に移動しますand。このように、暗黙的な変換を適用する場合restrictionToConjunctionBuilder、コンパイラーはパラメーターからすべてのタイプパラメーター(つまり、uniqyeタイプパラメーターL)を完全に推測できますrestriction。次に、それを適用すると、そのパラメータからand推測できますRrhs

于 2012-10-18T08:38:33.247 に答える