使用`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 的建议 我尝试添加 DummyImplicit
s:
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
}
}
但是当我添加 DummyImplcit
s 时,它开始出错(第二个程序):
[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
调用了正确的重载,成功。
考虑以下程序:
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 的建议 我尝试添加 DummyImplicit
s:
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
}
}
但是当我添加 DummyImplcit
s 时,它开始出错(第二个程序):
[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
调用了正确的重载,成功。