简单的问题 - "错误:缺少方法的参数列表"

时间:2018-01-18 12:04:05

标签: scala

我有一个简单的类和一个使用apply方法重载的伴随对象:

case class A(val s: String,
         val x: Int,
         val y: Int,
         val z: Int,
         val foo: Int => Int,
         val l: Option[List[String]])

object A {
    def apply(s: String, x: Int, y: Int, z: Int, foo: Int => Int) =
        new A(s, x, y, z, foo, None)

    def apply(s: String, x: Int, y: Int, z: Int, foo: Int => Int, l: List[String]) =
        new A(s, x, y, z, foo, Some(l))
}

我们还定义了一个函数:

def foo(x: Int): Int = x + 1

使用第一个构造函数:

scala> val a1 = A("a1", 1, 2, 3, foo)
a1: A = A(a1,1,2,3,$$Lambda$1842/2112068307@598e02f0,None)

然而,使用第二个不会:

val a2 = A("a1", 1, 2, 3, foo, List("b1", "b2"))
<console>:24: error: missing argument list for method foo
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `foo _` or `foo(_)` instead of `foo`.
       val a2 = A("a1", 1, 2, 3, foo, List("b1", "b2"))

问题:我需要在foo _示例中传递foo(_)a1而不是foo的原因是什么?另外,我可以重新定义我的课程,以便只使用foo吗?

2 个答案:

答案 0 :(得分:2)

我无法解释这一点。我的第一个想法是它与类型擦除有关,正如slouc所说的那样,但后来我更仔细地查看了签名,即使在擦除之后它们都没有相同的类型签名:

案例类apply

String, Int, Int, Int, Function1, Option

伴随对象apply 1:

String, Int, Int, Int, Function1

伴随对象apply 2:

String, Int, Int, Int, Function1, List

所以,我不明白这是怎么回事。

尝试使其工作我已经注意到,如果将第二个apply方法重命名为其他方法,它将正常工作:

scala> val a1 = A("a1", 1, 2, 3, foo)
a1: A = A(a1,1,2,3,$$Lambda$1286/1904652802@6b649efa,None)

scala> val a2 = A.apply2("a1", 1, 2, 3, foo, List("b1", "b2"))
a2: A = A(a1,1,2,3,$$Lambda$1287/866073173@2dd63e3,Some(List(b1, b2)))

或定义不在随播对象中的两个apply方法:

object B {

    def apply(s: String, x: Int, y: Int, z: Int, foo: Int => Int): A =
      new A(s, x, y, z, foo, None)

    def apply(s: String, x: Int, y: Int, z: Int, foo: Int => Int, l: List[String]): A =
      new A(s, x, y, z, foo, Some(l))
}

REPL:

scala> val a1 = B("a1", 1, 2, 3, foo)
a1: A = A(a1,1,2,3,$$Lambda$1351/814507488@50fa5938,None)

scala> val a2 = B("a1", 1, 2, 3, foo, List("b1", "b2"))
a2: A = A(a1,1,2,3,$$Lambda$1352/613231852@5d77be8e,Some(List(b1, b2)))

第三种方法,如Robert Udah所述,将foo定义为函数文字(x: Int) => x + 1也解决了这个问题。但是,它不必是val,也可以是def

def foo = (x: Int) => x + 1

答案 1 :(得分:0)

如果将foo声明为函数val

,则可以正常工作
scala> val foo = (x: Int) => x + 1
foo: Int => Int = <function1>

scala> val a1 = A("a1", 1, 2, 3, foo)
a1: A = A(a1,1,2,3,<function1>,None)

scala> val a2 = A("a1", 1, 2, 3, foo, List("b1", "b2"))
a2: A = A(a1,1,2,3,<function1>,Some(List(b1, b2)))

为什么def foo适用于a1我不确定,但它可能与case class A期待函数而不是方法有关,因为这些显然是两个不同的东西在斯卡拉。

Here is a post that might explain better