使用`DummyImplicit` (Scala) 的问题

Problems in using `DummyImplicit` (Scala)

考虑以下程序:

  class myClass {
    def property[T](name: Symbol)(f: T => Boolean): Unit = {
      // do something
    }

    def property1[T](name: Symbol)(f: T => List[Int]): Unit = {
      // do something
    }
  }

  object spamDataModel extends myClass {
    property[Int]('myBoolean) {
      x:Int=> true
    }
  }

假设我想将方法​​的名称 property1 更改为 property,同时保留这两个名称。由于类型擦除,这是不可能的,除非我做一些技巧。

希望得到 here 的建议 我尝试添加 DummyImplicits:

class myClass {
    def property[T](name: Symbol)(f: T => Boolean)(): Unit = {
      // do something
    }

    def property[T](name: Symbol)(f: T => List[Int])(implicit d: DummyImplicit): Unit = {
      // do something
    }
  }

  object spamDataModel extends myClass {
    property[Int]('myBoolean) {
      x:Int=> true
    }
  }

但是当我添加 DummyImplcits 时,它开始出错(第二个程序):

[error] /Users/i-danielk/ideaProjects/saul/saul-core/src/main/scala/edu/illinois/cs/cogcomp/saul/datamodel/DataModel.scala:261: ambiguous reference to overloaded definition,
[error] both method property in class myClass of type (name: Symbol)(f: Int => List[Int])Unit
[error] and  method property in class myClass of type (name: Symbol)(f: Int => Boolean)(implicit d1: DummyImplicit)Unit
[error] match argument types (Symbol)
[error]     property[Int]('myBoolean) {
[error]             ^
[warn] two warnings found
[error] one error found

通过使用 DummyImplicit 你只解决了擦除问题,但现在你有另一个问题:两个重载具有完全相同的(第一个)参数列表。推理一次只处理一个参数列表,因此如果两个重载具有相同的第一个参数列表,编译器就无法决定要调用哪个。

解决这个问题的一种方法是使用 Magnet Pattern.

但是你也可以用一种更简单的方法来解决它,通过一个单一的 property 方法(就像你对磁铁模式所做的那样)并且简单地将它 return a class 本身有两个 apply 方法:

class myClass {
  class PropertyApply[T] private[myClass] (name: Symbol) {
    def apply(f: T => Boolean): Unit = {
      // do something
      println("Called property with f: T => Boolean")
    }
    def apply(f: T => List[Int])(implicit d: DummyImplicit): Unit = {
      // do something
      println("Called property with f: T => List[Int]")
    }
  }
  def property[T](name: Symbol) = new PropertyApply[T](name)
}

object spamDataModel extends myClass {
  property[Int]('myBoolean) {
    x:Int => true
  }
}

让我们看看:

scala> spamDataModel
Called property with f: T => Boolean
res4: spamDataModel.type = spamDataModel$@20880a03

调用了正确的重载,成功。