Scala:带有implicits,currying和defaults的重载方法之间的偏好

时间:2015-07-09 11:49:25

标签: scala

以下简单的代码无法编译:

object O { 
  def apply(s:String, o:Int=5)(implicit i:String) = { 
    println("am first"); 
    s 
  }

  def apply(s:String)(o:Boolean*) = { 
    println("am second"); 
    o 
  } 
}

object Main extends App {
  implicit val myS = "foo"
  O("test")
}

错误

error: missing arguments for method apply in object O;
follow this method with `_' if you want to treat it as a partially applied function
  O("test")
   ^
one error found

这似乎是因为编译器更喜欢第二个apply。但为什么会这样呢?特别是考虑到满足第一apply的应用条件?如果我删除第二个apply,那么这段代码编译得很好。

有没有办法指导"编译器正确编译这个?或者我被迫创建两个不同的方法名称?

2 个答案:

答案 0 :(得分:3)

您是对的,Scala编译器可能更智能。问题是没有人想要为此提出新的规范。它会非常复杂。

有办法解决这个限制。

1。用apply中的模式匹配替换重载以选择两个函数之一

def apply(s: String, i: Option[Int] = None) = {
  i match {
    case Some(n) => // call the 1st
    case None => // call the 2nd
 }

}

然后:

apply("test", Some(5)) => ... // if we want the first
apply("test") => ... // if we want the second

2。使用重载但具有两个函数的不同参数名称:

def apply(apple: String, o: Int = 5)(implicit i: String)
def apply(banana: String)(o: Boolean*) 

然后:

apply(apple = "test") // if we want the first    
apply(banana = "test") // if we want the second

答案 1 :(得分:0)

让我们毫不含糊地考虑这种情况

object O {
  def apply(s: String, o: Int = 5) = {
    println("am first")
  }

  def apply(s: String) = {
    println("am second")
  }
}

在这种情况下,O("test")将使用第二次应用进行编译,因此在这种情况下您无法使用默认参数。这里没有任何改变。如果您明确提供Int参数,则您将使用first apply编译。